• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.settings.bluetooth;
18 
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import android.os.SystemProperties;
22 import android.util.AttributeSet;
23 import android.util.Pair;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 import androidx.preference.Preference;
28 
29 import com.android.car.settings.R;
30 import com.android.car.settings.common.MultiActionPreference;
31 import com.android.car.settings.common.ToggleButtonActionItem;
32 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
33 
34 /**
35  * Preference which represents a specific {@link CachedBluetoothDevice}. The title, icon, and
36  * summary are kept in sync with the device when the preference is shown. When the device is busy,
37  * the preference is disabled. The equality and sort order of this preference is determined by the
38  * underlying cached device {@link CachedBluetoothDevice#equals(Object)} and {@link
39  * CachedBluetoothDevice#compareTo(CachedBluetoothDevice)}. If two devices are considered equal, the
40  * default preference sort ordering is used (see {@link #compareTo(Preference)}.
41  */
42 public class BluetoothDevicePreference extends MultiActionPreference {
43 
44     private final CachedBluetoothDevice mCachedDevice;
45     private final boolean mShowDevicesWithoutNames;
46     private final boolean mShowDisconnectedStateSubtitle;
47     private final CachedBluetoothDevice.Callback mDeviceCallback = this::refreshUi;
48 
49     private UpdateToggleButtonListener mUpdateToggleButtonListener;
50 
BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice)51     public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
52         this(context, cachedDevice, /* showDisconnectedStateSubtitle= */ true);
53     }
54 
BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice, boolean showDisconnectedStateSubtitle)55     public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
56             boolean showDisconnectedStateSubtitle) {
57         super(context);
58         mCachedDevice = cachedDevice;
59         mShowDisconnectedStateSubtitle = showDisconnectedStateSubtitle;
60         mShowDevicesWithoutNames = SystemProperties.getBoolean(
61                 BluetoothUtils.BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
62     }
63 
64     @Override
init(@ullable AttributeSet attrs)65     protected void init(@Nullable AttributeSet attrs) {
66         mActionItemArray[0] = new ToggleButtonActionItem(this);
67         mActionItemArray[1] = new ToggleButtonActionItem(this);
68         mActionItemArray[2] = new ToggleButtonActionItem(this);
69         super.init(attrs);
70 
71         // Hide actions by default.
72         mActionItemArray[0].setVisible(false);
73         mActionItemArray[1].setVisible(false);
74         mActionItemArray[2].setVisible(false);
75     }
76 
77     /**
78      * Returns the {@link CachedBluetoothDevice} represented by this preference.
79      */
getCachedDevice()80     public CachedBluetoothDevice getCachedDevice() {
81         return mCachedDevice;
82     }
83 
84     /**
85      * Sets the {@link UpdateToggleButtonListener} that will be called when the toggle buttons
86      * may need to change state.
87      */
setToggleButtonUpdateListener(UpdateToggleButtonListener listener)88     public void setToggleButtonUpdateListener(UpdateToggleButtonListener listener) {
89         mUpdateToggleButtonListener = listener;
90     }
91 
92     @Override
onAttached()93     public void onAttached() {
94         super.onAttached();
95         mCachedDevice.registerCallback(mDeviceCallback);
96         refreshUi();
97     }
98 
99     @Override
onDetached()100     public void onDetached() {
101         super.onDetached();
102         mCachedDevice.unregisterCallback(mDeviceCallback);
103     }
104 
refreshUi()105     private void refreshUi() {
106         setTitle(mCachedDevice.getName());
107         setSummary(mCachedDevice.getCarConnectionSummary(/* shortSummary= */ true,
108                 mShowDisconnectedStateSubtitle));
109 
110         Pair<Drawable, String> pair = com.android.settingslib.bluetooth.BluetoothUtils
111                 .getBtClassDrawableWithDescription(getContext(), mCachedDevice);
112         if (pair.first != null) {
113             setIcon(pair.first);
114             getIcon().setTintList(getContext().getColorStateList(R.color.icon_color_default));
115         }
116 
117         setEnabled(!mCachedDevice.isBusy());
118         setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());
119 
120         if (mUpdateToggleButtonListener != null) {
121             mUpdateToggleButtonListener.updateToggleButtonState(this);
122         }
123         // Notify since the ordering may have changed.
124         notifyHierarchyChanged();
125     }
126 
getConnectionSummary()127     private CharSequence getConnectionSummary() {
128         CharSequence summary = mCachedDevice.getCarConnectionSummary(/* shortSummary= */ true,
129                 mShowDisconnectedStateSubtitle);
130 
131         if (mCachedDevice.isConnected()) {
132             Pair<Drawable, String> pair = com.android.settingslib.bluetooth.BluetoothUtils
133                     .getBtClassDrawableWithDescription(getContext(), mCachedDevice);
134             String connectedDeviceType = pair.second;
135 
136             if (connectedDeviceType != null && !connectedDeviceType.isEmpty()) {
137                 summary += " · " + connectedDeviceType;
138             }
139         }
140 
141         return summary;
142     }
143 
144     @Override
equals(Object o)145     public boolean equals(Object o) {
146         if (!(o instanceof BluetoothDevicePreference)) {
147             return false;
148         }
149         return mCachedDevice.equals(((BluetoothDevicePreference) o).mCachedDevice);
150     }
151 
152     @Override
hashCode()153     public int hashCode() {
154         return mCachedDevice.hashCode();
155     }
156 
157     @Override
compareTo(@onNull Preference another)158     public int compareTo(@NonNull Preference another) {
159         if (!(another instanceof BluetoothDevicePreference)) {
160             // Rely on default sort.
161             return super.compareTo(another);
162         }
163 
164         return mCachedDevice
165                 .compareTo(((BluetoothDevicePreference) another).mCachedDevice);
166     }
167 
168     @Override
getActionItem(ActionItem actionItem)169     public ToggleButtonActionItem getActionItem(ActionItem actionItem) {
170         switch(actionItem) {
171             case ACTION_ITEM1:
172                 return (ToggleButtonActionItem) mActionItemArray[0];
173             case ACTION_ITEM2:
174                 return (ToggleButtonActionItem) mActionItemArray[1];
175             case ACTION_ITEM3:
176                 return (ToggleButtonActionItem) mActionItemArray[2];
177             default:
178                 throw new IllegalArgumentException("Invalid button requested");
179         }
180     }
181 
182     /**
183      * Callback for when toggle buttons may need to be updated
184      */
185     public interface UpdateToggleButtonListener {
186         /**
187          * Preference state has changed and toggle button changes should be handled.
188          *
189          * @param preference the preference that has been changed
190          */
updateToggleButtonState(BluetoothDevicePreference preference)191         void updateToggleButtonState(BluetoothDevicePreference preference);
192     }
193 }
194