Files
app_Settings/src/com/android/settings/bluetooth/HidProfile.java
Jake Hamby 18c4317b93 Show correct A2DP connection status in Bluetooth settings.
When BluetoothSettings is entered via QuickSettings while an A2DP
device is connected, we aren't showing the device connection
status in the UI, because the device list is created before we've
connected to the A2DP and Headset profile services, and we weren't
refreshing the device list UI after getting the callback for
onServiceConnected() and retrieving the list of connected devices.

Add a line to HeadsetServiceListener.onServiceConnected() to call
device.refresh() after we call device.onProfileStateChanged() to
refresh the device list UI. Also copy the logic into A2dpProfile's
onServiceConnected() callback so it will refresh the UI for any
connected A2DP devices.

The reason this bug doesn't show up when entering BT settings
from the main Settings screen is because the onServiceConnected()
callbacks happen before the device list is initialized, so the
UI items are created with the correct connection status. For the
same reason, the bug doesn't occur if the Settings app is already
running and we re-enter it via Bluetooth QuickSettings.

Bug: 8724247
Change-Id: I1a993636ecab18dd6e980e3b4d2485bbed256d74
2013-04-30 13:51:38 -07:00

202 lines
6.9 KiB
Java
Executable File

/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
import com.android.settings.R;
import java.util.List;
/**
* HidProfile handles Bluetooth HID profile.
*/
final class HidProfile implements LocalBluetoothProfile {
private static final String TAG = "HidProfile";
private static boolean V = true;
private BluetoothInputDevice mService;
private boolean mIsProfileReady;
private final LocalBluetoothAdapter mLocalAdapter;
private final CachedBluetoothDeviceManager mDeviceManager;
private final LocalBluetoothProfileManager mProfileManager;
static final String NAME = "HID";
// Order of this profile in device profiles list
private static final int ORDINAL = 3;
// These callbacks run on the main thread.
private final class InputDeviceServiceListener
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (V) Log.d(TAG,"Bluetooth service connected");
mService = (BluetoothInputDevice) proxy;
// We just bound to the service, so refresh the UI for any connected HID devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
while (!deviceList.isEmpty()) {
BluetoothDevice nextDevice = deviceList.remove(0);
CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
// we may add a new device here, but generally this should not happen
if (device == null) {
Log.w(TAG, "HidProfile found new device: " + nextDevice);
device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
}
device.onProfileStateChanged(HidProfile.this, BluetoothProfile.STATE_CONNECTED);
device.refresh();
}
mIsProfileReady=true;
}
public void onServiceDisconnected(int profile) {
if (V) Log.d(TAG,"Bluetooth service disconnected");
mIsProfileReady=false;
}
}
public boolean isProfileReady() {
return mIsProfileReady;
}
HidProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) {
mLocalAdapter = adapter;
mDeviceManager = deviceManager;
mProfileManager = profileManager;
adapter.getProfileProxy(context, new InputDeviceServiceListener(),
BluetoothProfile.INPUT_DEVICE);
}
public boolean isConnectable() {
return true;
}
public boolean isAutoConnectable() {
return true;
}
public boolean connect(BluetoothDevice device) {
if (mService == null) return false;
return mService.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
if (mService == null) return false;
return mService.disconnect(device);
}
public int getConnectionStatus(BluetoothDevice device) {
if (mService == null) {
return BluetoothProfile.STATE_DISCONNECTED;
}
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
return !deviceList.isEmpty() && deviceList.get(0).equals(device)
? mService.getConnectionState(device)
: BluetoothProfile.STATE_DISCONNECTED;
}
public boolean isPreferred(BluetoothDevice device) {
if (mService == null) return false;
return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
}
public int getPreferred(BluetoothDevice device) {
if (mService == null) return BluetoothProfile.PRIORITY_OFF;
return mService.getPriority(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
if (mService == null) return;
if (preferred) {
if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
}
} else {
mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
}
}
public String toString() {
return NAME;
}
public int getOrdinal() {
return ORDINAL;
}
public int getNameResource(BluetoothDevice device) {
// TODO: distinguish between keyboard and mouse?
return R.string.bluetooth_profile_hid;
}
public int getSummaryResourceForDevice(BluetoothDevice device) {
int state = getConnectionStatus(device);
switch (state) {
case BluetoothProfile.STATE_DISCONNECTED:
return R.string.bluetooth_hid_profile_summary_use_for;
case BluetoothProfile.STATE_CONNECTED:
return R.string.bluetooth_hid_profile_summary_connected;
default:
return Utils.getConnectionStateSummary(state);
}
}
public int getDrawableResource(BluetoothClass btClass) {
if (btClass == null) {
return R.drawable.ic_bt_keyboard_hid;
}
return getHidClassDrawable(btClass);
}
static int getHidClassDrawable(BluetoothClass btClass) {
switch (btClass.getDeviceClass()) {
case BluetoothClass.Device.PERIPHERAL_KEYBOARD:
case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING:
return R.drawable.ic_bt_keyboard_hid;
case BluetoothClass.Device.PERIPHERAL_POINTING:
return R.drawable.ic_bt_pointing_hid;
default:
return R.drawable.ic_bt_misc_hid;
}
}
protected void finalize() {
if (V) Log.d(TAG, "finalize()");
if (mService != null) {
try {
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.INPUT_DEVICE,
mService);
mService = null;
}catch (Throwable t) {
Log.w(TAG, "Error cleaning up HID proxy", t);
}
}
}
}