OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / qs / tiles / BluetoothTile.java
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
17 package com.android.systemui.qs.tiles;
18
19 import android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothDevice;
21 import android.bluetooth.BluetoothProfile;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.provider.Settings;
25 import android.text.TextUtils;
26 import android.view.View;
27 import android.view.ViewGroup;
28 import android.widget.Button;
29 import android.widget.Switch;
30
31 import com.android.internal.logging.MetricsLogger;
32 import com.android.internal.logging.MetricsProto.MetricsEvent;
33 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
34 import com.android.systemui.R;
35 import com.android.systemui.qs.QSDetailItems;
36 import com.android.systemui.qs.QSDetailItems.Item;
37 import com.android.systemui.qs.QSTile;
38 import com.android.systemui.statusbar.policy.BluetoothController;
39
40 import java.util.ArrayList;
41 import java.util.Collection;
42
43 /** Quick settings tile: Bluetooth **/
44 public class BluetoothTile extends QSTile<QSTile.BooleanState>  {
45     private static final Intent BLUETOOTH_SETTINGS = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
46
47     private final BluetoothController mController;
48     private final BluetoothDetailAdapter mDetailAdapter;
49
50     public BluetoothTile(Host host) {
51         super(host);
52         mController = host.getBluetoothController();
53         mDetailAdapter = new BluetoothDetailAdapter();
54     }
55
56     @Override
57     public DetailAdapter getDetailAdapter() {
58         return mDetailAdapter;
59     }
60
61     @Override
62     public BooleanState newTileState() {
63         return new BooleanState();
64     }
65
66     @Override
67     public void setListening(boolean listening) {
68         if (listening) {
69             mController.addStateChangedCallback(mCallback);
70         } else {
71             mController.removeStateChangedCallback(mCallback);
72         }
73     }
74
75     @Override
76     protected void handleSecondaryClick() {
77         // Secondary clicks are header clicks, just toggle.
78         final boolean isEnabled = (Boolean)mState.value;
79         MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
80         mController.setBluetoothEnabled(!isEnabled);
81     }
82
83     @Override
84     public Intent getLongClickIntent() {
85         return new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
86     }
87
88     @Override
89     protected void handleClick() {
90         if (!mController.canConfigBluetooth()) {
91             mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
92             return;
93         }
94         showDetail(true);
95         if (!mState.value) {
96             mState.value = true;
97             mController.setBluetoothEnabled(true);
98         }
99     }
100
101     @Override
102     public CharSequence getTileLabel() {
103         return mContext.getString(R.string.quick_settings_bluetooth_label);
104     }
105
106     @Override
107     protected void handleUpdateState(BooleanState state, Object arg) {
108         final boolean enabled = mController.isBluetoothEnabled();
109         final boolean connected = mController.isBluetoothConnected();
110         final boolean connecting = mController.isBluetoothConnecting();
111         state.value = enabled;
112         state.autoMirrorDrawable = false;
113         state.minimalContentDescription =
114                 mContext.getString(R.string.accessibility_quick_settings_bluetooth);
115         if (enabled) {
116             state.label = null;
117             if (connected) {
118                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
119                 state.label = mController.getLastDeviceName();
120                 state.contentDescription = mContext.getString(
121                         R.string.accessibility_bluetooth_name, state.label);
122                 state.minimalContentDescription = state.minimalContentDescription + ","
123                         + state.contentDescription;
124             } else if (connecting) {
125                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connecting);
126                 state.contentDescription = mContext.getString(
127                         R.string.accessibility_quick_settings_bluetooth_connecting);
128                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
129                 state.minimalContentDescription = state.minimalContentDescription + ","
130                         + state.contentDescription;
131             } else {
132                 state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_on);
133                 state.contentDescription = mContext.getString(
134                         R.string.accessibility_quick_settings_bluetooth_on) + ","
135                         + mContext.getString(R.string.accessibility_not_connected);
136                 state.minimalContentDescription = state.minimalContentDescription + ","
137                         + mContext.getString(R.string.accessibility_not_connected);
138             }
139             if (TextUtils.isEmpty(state.label)) {
140                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
141             }
142         } else {
143             state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_off);
144             state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
145             state.contentDescription = mContext.getString(
146                     R.string.accessibility_quick_settings_bluetooth_off);
147         }
148
149         CharSequence bluetoothName = state.label;
150         if (connected) {
151             bluetoothName = state.dualLabelContentDescription = mContext.getString(
152                     R.string.accessibility_bluetooth_name, state.label);
153         }
154         state.dualLabelContentDescription = bluetoothName;
155         state.contentDescription = state.contentDescription + "," + mContext.getString(
156                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
157         state.expandedAccessibilityClassName = Button.class.getName();
158         state.minimalAccessibilityClassName = Switch.class.getName();
159     }
160
161     @Override
162     public int getMetricsCategory() {
163         return MetricsEvent.QS_BLUETOOTH;
164     }
165
166     @Override
167     protected String composeChangeAnnouncement() {
168         if (mState.value) {
169             return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
170         } else {
171             return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_off);
172         }
173     }
174
175     @Override
176     public boolean isAvailable() {
177         return mController.isBluetoothSupported();
178     }
179
180     private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
181         @Override
182         public void onBluetoothStateChange(boolean enabled) {
183             refreshState();
184         }
185
186         @Override
187         public void onBluetoothDevicesChanged() {
188             mUiHandler.post(new Runnable() {
189                 @Override
190                 public void run() {
191                     mDetailAdapter.updateItems();
192                 }
193             });
194             refreshState();
195         }
196     };
197
198     private final class BluetoothDetailAdapter implements DetailAdapter, QSDetailItems.Callback {
199         private QSDetailItems mItems;
200
201         @Override
202         public CharSequence getTitle() {
203             return mContext.getString(R.string.quick_settings_bluetooth_label);
204         }
205
206         @Override
207         public Boolean getToggleState() {
208             return mState.value;
209         }
210
211         @Override
212         public boolean getToggleEnabled() {
213             return mController.getBluetoothState() == BluetoothAdapter.STATE_OFF
214                     || mController.getBluetoothState() == BluetoothAdapter.STATE_ON;
215         }
216
217         @Override
218         public Intent getSettingsIntent() {
219             return BLUETOOTH_SETTINGS;
220         }
221
222         @Override
223         public void setToggleState(boolean state) {
224             MetricsLogger.action(mContext, MetricsEvent.QS_BLUETOOTH_TOGGLE, state);
225             mController.setBluetoothEnabled(state);
226             showDetail(false);
227         }
228
229         @Override
230         public int getMetricsCategory() {
231             return MetricsEvent.QS_BLUETOOTH_DETAILS;
232         }
233
234         @Override
235         public View createDetailView(Context context, View convertView, ViewGroup parent) {
236             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
237             mItems.setTagSuffix("Bluetooth");
238             mItems.setEmptyState(R.drawable.ic_qs_bluetooth_detail_empty,
239                     R.string.quick_settings_bluetooth_detail_empty_text);
240             mItems.setCallback(this);
241             updateItems();
242             setItemsVisible(mState.value);
243             return mItems;
244         }
245
246         public void setItemsVisible(boolean visible) {
247             if (mItems == null) return;
248             mItems.setItemsVisible(visible);
249         }
250
251         private void updateItems() {
252             if (mItems == null) return;
253             ArrayList<Item> items = new ArrayList<Item>();
254             final Collection<CachedBluetoothDevice> devices = mController.getDevices();
255             if (devices != null) {
256                 for (CachedBluetoothDevice device : devices) {
257                     if (device.getBondState() == BluetoothDevice.BOND_NONE) continue;
258                     final Item item = new Item();
259                     item.icon = R.drawable.ic_qs_bluetooth_on;
260                     item.line1 = device.getName();
261                     int state = device.getMaxConnectionState();
262                     if (state == BluetoothProfile.STATE_CONNECTED) {
263                         item.icon = R.drawable.ic_qs_bluetooth_connected;
264                         item.line2 = mContext.getString(R.string.quick_settings_connected);
265                         item.canDisconnect = true;
266                     } else if (state == BluetoothProfile.STATE_CONNECTING) {
267                         item.icon = R.drawable.ic_qs_bluetooth_connecting;
268                         item.line2 = mContext.getString(R.string.quick_settings_connecting);
269                     }
270                     item.tag = device;
271                     items.add(item);
272                 }
273             }
274             mItems.setItems(items.toArray(new Item[items.size()]));
275         }
276
277         @Override
278         public void onDetailItemClick(Item item) {
279             if (item == null || item.tag == null) return;
280             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
281             if (device != null && device.getMaxConnectionState()
282                     == BluetoothProfile.STATE_DISCONNECTED) {
283                 mController.connect(device);
284             }
285         }
286
287         @Override
288         public void onDetailItemDisconnect(Item item) {
289             if (item == null || item.tag == null) return;
290             final CachedBluetoothDevice device = (CachedBluetoothDevice) item.tag;
291             if (device != null) {
292                 mController.disconnect(device);
293             }
294         }
295     }
296 }