Files
app_Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
Jason Monk 2071eda150 Workarounds to avoid removing all prefs
Removing all prefs causes ugly animations, so avoid it at all cost
and cache all the prefs (while still added) as long as possible.

Bug: 26271353
Change-Id: I33b84d751938b460f4b66c0158057407dd45d974
2016-02-26 11:00:01 -05:00

279 lines
9.2 KiB
Java

/*
* Copyright (C) 2008 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.app.AlertDialog;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.DialogInterface;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import com.android.settings.R;
import com.android.settings.search.Index;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HidProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import java.util.List;
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
/**
* BluetoothDevicePreference is the preference type used to display each remote
* Bluetooth device in the Bluetooth Settings screen.
*/
public final class BluetoothDevicePreference extends Preference implements
CachedBluetoothDevice.Callback, OnClickListener {
private static final String TAG = "BluetoothDevicePreference";
private static int sDimAlpha = Integer.MIN_VALUE;
private final CachedBluetoothDevice mCachedDevice;
private OnClickListener mOnSettingsClickListener;
private AlertDialog mDisconnectDialog;
public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
super(context);
if (sDimAlpha == Integer.MIN_VALUE) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
sDimAlpha = (int) (outValue.getFloat() * 255);
}
mCachedDevice = cachedDevice;
setLayoutResource(R.layout.preference_bt_icon);
if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (! um.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)) {
setWidgetLayoutResource(R.layout.preference_bluetooth);
}
}
mCachedDevice.registerCallback(this);
onDeviceAttributesChanged();
}
void rebind() {
notifyChanged();
}
CachedBluetoothDevice getCachedDevice() {
return mCachedDevice;
}
public void setOnSettingsClickListener(OnClickListener listener) {
mOnSettingsClickListener = listener;
}
@Override
protected void onPrepareForRemoval() {
super.onPrepareForRemoval();
mCachedDevice.unregisterCallback(this);
if (mDisconnectDialog != null) {
mDisconnectDialog.dismiss();
mDisconnectDialog = null;
}
}
public void onDeviceAttributesChanged() {
/*
* The preference framework takes care of making sure the value has
* changed before proceeding. It will also call notifyChanged() if
* any preference info has changed from the previous value.
*/
setTitle(mCachedDevice.getName());
int summaryResId = mCachedDevice.getConnectionSummary();
if (summaryResId != 0) {
setSummary(summaryResId);
} else {
setSummary(null); // empty summary for unpaired devices
}
int iconResId = getBtClassDrawable();
if (iconResId != 0) {
setIcon(iconResId);
}
// Used to gray out the item
setEnabled(!mCachedDevice.isBusy());
// This could affect ordering, so notify that
notifyHierarchyChanged();
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
// Disable this view if the bluetooth enable/disable preference view is off
if (null != findPreferenceInHierarchy("bt_checkbox")) {
setDependency("bt_checkbox");
}
if (mCachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
ImageView deviceDetails = (ImageView) view.findViewById(R.id.deviceDetails);
if (deviceDetails != null) {
deviceDetails.setOnClickListener(this);
deviceDetails.setTag(mCachedDevice);
}
}
super.onBindViewHolder(view);
}
public void onClick(View v) {
// Should never be null by construction
if (mOnSettingsClickListener != null) {
mOnSettingsClickListener.onClick(v);
}
}
@Override
public boolean equals(Object o) {
if ((o == null) || !(o instanceof BluetoothDevicePreference)) {
return false;
}
return mCachedDevice.equals(
((BluetoothDevicePreference) o).mCachedDevice);
}
@Override
public int hashCode() {
return mCachedDevice.hashCode();
}
@Override
public int compareTo(Preference another) {
if (!(another instanceof BluetoothDevicePreference)) {
// Rely on default sort
return super.compareTo(another);
}
return mCachedDevice
.compareTo(((BluetoothDevicePreference) another).mCachedDevice);
}
void onClicked() {
int bondState = mCachedDevice.getBondState();
if (mCachedDevice.isConnected()) {
askDisconnect();
} else if (bondState == BluetoothDevice.BOND_BONDED) {
mCachedDevice.connect(true);
} else if (bondState == BluetoothDevice.BOND_NONE) {
pair();
}
}
// Show disconnect confirmation dialog for a device.
private void askDisconnect() {
Context context = getContext();
String name = mCachedDevice.getName();
if (TextUtils.isEmpty(name)) {
name = context.getString(R.string.bluetooth_device);
}
String message = context.getString(R.string.bluetooth_disconnect_all_profiles, name);
String title = context.getString(R.string.bluetooth_disconnect_title);
DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mCachedDevice.disconnect();
}
};
mDisconnectDialog = Utils.showDisconnectDialog(context,
mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
}
private void pair() {
if (!mCachedDevice.startPairing()) {
Utils.showError(getContext(), mCachedDevice.getName(),
R.string.bluetooth_pairing_error_message);
} else {
final Context context = getContext();
SearchIndexableRaw data = new SearchIndexableRaw(context);
data.className = BluetoothSettings.class.getName();
data.title = mCachedDevice.getName();
data.screenTitle = context.getResources().getString(R.string.bluetooth_settings);
data.iconResId = R.drawable.ic_settings_bluetooth;
data.enabled = true;
Index.getInstance(context).updateFromSearchIndexableData(data);
}
}
private int getBtClassDrawable() {
BluetoothClass btClass = mCachedDevice.getBtClass();
if (btClass != null) {
switch (btClass.getMajorDeviceClass()) {
case BluetoothClass.Device.Major.COMPUTER:
return R.drawable.ic_bt_laptop;
case BluetoothClass.Device.Major.PHONE:
return R.drawable.ic_bt_cellphone;
case BluetoothClass.Device.Major.PERIPHERAL:
return HidProfile.getHidClassDrawable(btClass);
case BluetoothClass.Device.Major.IMAGING:
return R.drawable.ic_bt_imaging;
default:
// unrecognized device class; continue
}
} else {
Log.w(TAG, "mBtClass is null");
}
List<LocalBluetoothProfile> profiles = mCachedDevice.getProfiles();
for (LocalBluetoothProfile profile : profiles) {
int resId = profile.getDrawableResource(btClass);
if (resId != 0) {
return resId;
}
}
if (btClass != null) {
if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
return R.drawable.ic_bt_headphones_a2dp;
}
if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
return R.drawable.ic_bt_headset_hfp;
}
}
return R.drawable.ic_settings_bluetooth;
}
}