BluetoothTile.java revision 06d3bca095aecbb7542ebf4bdaa56b368261dd9d
1/*
2 * Copyright (C) 2014 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
17package com.android.systemui.qs.tiles;
18
19import android.content.Context;
20import android.content.Intent;
21import android.provider.Settings;
22import android.text.TextUtils;
23import android.view.View;
24import android.view.ViewGroup;
25
26import com.android.systemui.R;
27import com.android.systemui.qs.QSDetailItems;
28import com.android.systemui.qs.QSDetailItems.Item;
29import com.android.systemui.qs.QSTile;
30import com.android.systemui.statusbar.policy.BluetoothController;
31import com.android.systemui.statusbar.policy.BluetoothController.PairedDevice;
32
33import java.util.Set;
34
35/** Quick settings tile: Bluetooth **/
36public class BluetoothTile extends QSTile<QSTile.BooleanState>  {
37    private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
38
39    private final BluetoothController mController;
40    private final BluetoothDetailAdapter mDetailAdapter;
41
42    public BluetoothTile(Host host) {
43        super(host);
44        mController = host.getBluetoothController();
45        mDetailAdapter = new BluetoothDetailAdapter();
46    }
47
48    @Override
49    public boolean supportsDualTargets() {
50        return true;
51    }
52
53    @Override
54    public DetailAdapter getDetailAdapter() {
55        return mDetailAdapter;
56    }
57
58    @Override
59    protected BooleanState newTileState() {
60        return new BooleanState();
61    }
62
63    @Override
64    public void setListening(boolean listening) {
65        if (listening) {
66            mController.addStateChangedCallback(mCallback);
67        } else {
68            mController.removeStateChangedCallback(mCallback);
69        }
70    }
71
72    @Override
73    protected void handleClick() {
74        final boolean isEnabled = (Boolean)mState.value;
75        mController.setBluetoothEnabled(!isEnabled);
76    }
77
78    @Override
79    protected void handleSecondaryClick() {
80        mHost.startSettingsActivity(BLUETOOTH_SETTINGS);
81    }
82
83    @Override
84    protected void handleUpdateState(BooleanState state, Object arg) {
85        final boolean supported = mController.isBluetoothSupported();
86        final boolean enabled = mController.isBluetoothEnabled();
87        final boolean connected = mController.isBluetoothConnected();
88        final boolean connecting = mController.isBluetoothConnecting();
89        state.visible = supported;
90        state.value = enabled;
91        state.autoMirrorDrawable = false;
92        if (enabled) {
93            state.label = null;
94            if (connected) {
95                state.iconId = R.drawable.ic_qs_bluetooth_connected;
96                state.contentDescription = mContext.getString(
97                        R.string.accessibility_quick_settings_bluetooth_connected);
98                state.label = mController.getLastDeviceName();
99            } else if (connecting) {
100                state.iconId = R.drawable.ic_qs_bluetooth_connecting;
101                state.contentDescription = mContext.getString(
102                        R.string.accessibility_quick_settings_bluetooth_connecting);
103                state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
104            } else {
105                state.iconId = R.drawable.ic_qs_bluetooth_on;
106                state.contentDescription = mContext.getString(
107                        R.string.accessibility_quick_settings_bluetooth_on);
108            }
109            if (TextUtils.isEmpty(state.label)) {
110                state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
111            }
112        } else {
113            state.iconId = R.drawable.ic_qs_bluetooth_off;
114            state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
115            state.contentDescription = mContext.getString(
116                    R.string.accessibility_quick_settings_bluetooth_off);
117        }
118
119        String bluetoothName = state.label;
120        if (connected) {
121            bluetoothName = state.dualLabelContentDescription = mContext.getString(
122                    R.string.accessibility_bluetooth_name, state.label);
123        }
124        state.dualLabelContentDescription = bluetoothName;
125    }
126
127    @Override
128    protected String composeChangeAnnouncement() {
129        if (mState.value) {
130            return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
131        } else {
132            return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_off);
133        }
134    }
135
136    private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
137        @Override
138        public void onBluetoothStateChange(boolean enabled, boolean connecting) {
139            refreshState();
140        }
141        @Override
142        public void onBluetoothPairedDevicesChanged() {
143            mUiHandler.post(new Runnable() {
144                @Override
145                public void run() {
146                    mDetailAdapter.updateItems();
147                }
148            });
149        }
150    };
151
152    private final class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
153        private QSDetailItems mItems;
154
155        @Override
156        public int getTitle() {
157            return R.string.quick_settings_bluetooth_label;
158        }
159
160        @Override
161        public Boolean getToggleState() {
162            return mState.value;
163        }
164
165        @Override
166        public Intent getSettingsIntent() {
167            return BLUETOOTH_SETTINGS;
168        }
169
170        @Override
171        public void setToggleState(boolean state) {
172            mController.setBluetoothEnabled(state);
173            showDetail(false);
174        }
175
176        @Override
177        public View createDetailView(Context context, View convertView, ViewGroup parent) {
178            mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
179            mItems.setTagSuffix("Bluetooth");
180            mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
181                    R.string.quick_settings_bluetooth_detail_empty_text);
182            mItems.setCallback(this);
183            updateItems();
184            setItemsVisible(mState.value);
185            return mItems;
186        }
187
188        public void setItemsVisible(boolean visible) {
189            if (mItems == null) return;
190            mItems.setItemsVisible(visible);
191        }
192
193        private void updateItems() {
194            if (mItems == null) return;
195            Item[] items = null;
196            final Set<PairedDevice> devices = mController.getPairedDevices();
197            if (devices != null) {
198                items = new Item[devices.size()];
199                int i = 0;
200                for (PairedDevice device : devices) {
201                    final Item item = new Item();
202                    item.icon = R.drawable.ic_qs_bluetooth_on;
203                    item.line1 = device.name;
204                    if (device.state == PairedDevice.STATE_CONNECTED) {
205                        item.icon = R.drawable.ic_qs_bluetooth_connected;
206                        item.line2 = mContext.getString(R.string.quick_settings_connected);
207                        item.canDisconnect = true;
208                    } else if (device.state == PairedDevice.STATE_CONNECTING) {
209                        item.icon = R.drawable.ic_qs_bluetooth_connecting;
210                        item.line2 = mContext.getString(R.string.quick_settings_connecting);
211                    }
212                    item.tag = device;
213                    items[i++] = item;
214                }
215            }
216            mItems.setItems(items);
217        }
218
219        @Override
220        public void onDetailItemClick(Item item) {
221            if (item == null || item.tag == null) return;
222            final PairedDevice device = (PairedDevice) item.tag;
223            if (device != null && device.state == PairedDevice.STATE_DISCONNECTED) {
224                mController.connect(device);
225            }
226        }
227
228        @Override
229        public void onDetailItemDisconnect(Item item) {
230            if (item == null || item.tag == null) return;
231            final PairedDevice device = (PairedDevice) item.tag;
232            if (device != null) {
233                mController.disconnect(device);
234            }
235        }
236    }
237}
238