• 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     private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
44             "persist.bluetooth.showdeviceswithoutnames";
45 
46     private final CachedBluetoothDevice mCachedDevice;
47     private final boolean mShowDevicesWithoutNames;
48     private final boolean mShowDisconnectedStateSubtitle;
49     private final CachedBluetoothDevice.Callback mDeviceCallback = this::refreshUi;
50 
51     private UpdateToggleButtonListener mUpdateToggleButtonListener;
52 
BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice)53     public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
54         this(context, cachedDevice, /* showDisconnectedStateSubtitle= */ true);
55     }
56 
BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice, boolean showDisconnectedStateSubtitle)57     public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
58             boolean showDisconnectedStateSubtitle) {
59         super(context);
60         mCachedDevice = cachedDevice;
61         mShowDisconnectedStateSubtitle = showDisconnectedStateSubtitle;
62         mShowDevicesWithoutNames = SystemProperties.getBoolean(
63                 BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
64     }
65 
66     @Override
init(@ullable AttributeSet attrs)67     protected void init(@Nullable AttributeSet attrs) {
68         mActionItemArray[0] = new ToggleButtonActionItem(this);
69         mActionItemArray[1] = new ToggleButtonActionItem(this);
70         mActionItemArray[2] = new ToggleButtonActionItem(this);
71         super.init(attrs);
72 
73         // Hide actions by default.
74         mActionItemArray[0].setVisible(false);
75         mActionItemArray[1].setVisible(false);
76         mActionItemArray[2].setVisible(false);
77     }
78 
79     /**
80      * Returns the {@link CachedBluetoothDevice} represented by this preference.
81      */
getCachedDevice()82     public CachedBluetoothDevice getCachedDevice() {
83         return mCachedDevice;
84     }
85 
86     /**
87      * Sets the {@link UpdateToggleButtonListener} that will be called when the toggle buttons
88      * may need to change state.
89      */
setToggleButtonUpdateListener(UpdateToggleButtonListener listener)90     public void setToggleButtonUpdateListener(UpdateToggleButtonListener listener) {
91         mUpdateToggleButtonListener = listener;
92     }
93 
94     @Override
onAttached()95     public void onAttached() {
96         super.onAttached();
97         mCachedDevice.registerCallback(mDeviceCallback);
98         refreshUi();
99     }
100 
101     @Override
onDetached()102     public void onDetached() {
103         super.onDetached();
104         mCachedDevice.unregisterCallback(mDeviceCallback);
105     }
106 
refreshUi()107     private void refreshUi() {
108         setTitle(mCachedDevice.getName());
109         setSummary(mCachedDevice.getCarConnectionSummary(/* shortSummary= */ true,
110                 mShowDisconnectedStateSubtitle));
111 
112         Pair<Drawable, String> pair = com.android.settingslib.bluetooth.BluetoothUtils
113                 .getBtClassDrawableWithDescription(getContext(), mCachedDevice);
114         if (pair.first != null) {
115             setIcon(pair.first);
116             getIcon().setTintList(getContext().getColorStateList(R.color.icon_color_default));
117         }
118 
119         setEnabled(!mCachedDevice.isBusy());
120         setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());
121 
122         if (mUpdateToggleButtonListener != null) {
123             mUpdateToggleButtonListener.updateToggleButtonState(this);
124         }
125         // Notify since the ordering may have changed.
126         notifyHierarchyChanged();
127     }
128 
129     @Override
equals(Object o)130     public boolean equals(Object o) {
131         if (!(o instanceof BluetoothDevicePreference)) {
132             return false;
133         }
134         return mCachedDevice.equals(((BluetoothDevicePreference) o).mCachedDevice);
135     }
136 
137     @Override
hashCode()138     public int hashCode() {
139         return mCachedDevice.hashCode();
140     }
141 
142     @Override
compareTo(@onNull Preference another)143     public int compareTo(@NonNull Preference another) {
144         if (!(another instanceof BluetoothDevicePreference)) {
145             // Rely on default sort.
146             return super.compareTo(another);
147         }
148 
149         return mCachedDevice
150                 .compareTo(((BluetoothDevicePreference) another).mCachedDevice);
151     }
152 
153     @Override
getActionItem(ActionItem actionItem)154     public ToggleButtonActionItem getActionItem(ActionItem actionItem) {
155         switch(actionItem) {
156             case ACTION_ITEM1:
157                 return (ToggleButtonActionItem) mActionItemArray[0];
158             case ACTION_ITEM2:
159                 return (ToggleButtonActionItem) mActionItemArray[1];
160             case ACTION_ITEM3:
161                 return (ToggleButtonActionItem) mActionItemArray[2];
162             default:
163                 throw new IllegalArgumentException("Invalid button requested");
164         }
165     }
166 
167     /**
168      * Callback for when toggle buttons may need to be updated
169      */
170     public interface UpdateToggleButtonListener {
171         /**
172          * Preference state has changed and toggle button changes should be handled.
173          *
174          * @param preference the preference that has been changed
175          */
updateToggleButtonState(BluetoothDevicePreference preference)176         void updateToggleButtonState(BluetoothDevicePreference preference);
177     }
178 }
179