CellularTile.java revision 0ceef211875515c2a7531f9baeae46339e700f3a
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.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.res.Resources;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.Button;
27
28import com.android.internal.logging.MetricsLogger;
29import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
30import com.android.settingslib.net.DataUsageController;
31import com.android.systemui.R;
32import com.android.systemui.plugins.qs.QS.DetailAdapter;
33import com.android.systemui.qs.QSIconView;
34import com.android.systemui.qs.QSTile;
35import com.android.systemui.qs.SignalTileView;
36import com.android.systemui.statusbar.policy.NetworkController;
37import com.android.systemui.statusbar.policy.NetworkController.IconState;
38import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
39
40/** Quick settings tile: Cellular **/
41public class CellularTile extends QSTile<QSTile.SignalState> {
42    static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
43            "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
44
45    private final NetworkController mController;
46    private final DataUsageController mDataController;
47    private final CellularDetailAdapter mDetailAdapter;
48
49    private final CellSignalCallback mSignalCallback = new CellSignalCallback();
50
51    public CellularTile(Host host) {
52        super(host);
53        mController = host.getNetworkController();
54        mDataController = mController.getMobileDataController();
55        mDetailAdapter = new CellularDetailAdapter();
56    }
57
58    @Override
59    public SignalState newTileState() {
60        return new SignalState();
61    }
62
63    @Override
64    public DetailAdapter getDetailAdapter() {
65        return mDetailAdapter;
66    }
67
68    @Override
69    public void setListening(boolean listening) {
70        if (listening) {
71            mController.addSignalCallback(mSignalCallback);
72        } else {
73            mController.removeSignalCallback(mSignalCallback);
74        }
75    }
76
77    @Override
78    public QSIconView createTileView(Context context) {
79        return new SignalTileView(context);
80    }
81
82    @Override
83    public Intent getLongClickIntent() {
84        return CELLULAR_SETTINGS;
85    }
86
87    @Override
88    protected void handleClick() {
89        MetricsLogger.action(mContext, getMetricsCategory());
90        if (mDataController.isMobileDataSupported()) {
91            showDetail(true);
92        } else {
93            mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS);
94        }
95    }
96
97    @Override
98    public CharSequence getTileLabel() {
99        return mContext.getString(R.string.quick_settings_cellular_detail_title);
100    }
101
102    @Override
103    protected void handleUpdateState(SignalState state, Object arg) {
104        CallbackInfo cb = (CallbackInfo) arg;
105        if (cb == null) {
106            cb = mSignalCallback.mInfo;
107        }
108
109        final Resources r = mContext.getResources();
110        final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
111                : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
112                : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
113                : R.drawable.ic_qs_signal_no_signal;
114        state.icon = ResourceIcon.get(iconId);
115        state.isOverlayIconWide = cb.isDataTypeIconWide;
116        state.autoMirrorDrawable = !cb.noSim;
117        state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0;
118        state.filter = iconId != R.drawable.ic_qs_no_sim;
119        state.activityIn = cb.enabled && cb.activityIn;
120        state.activityOut = cb.enabled && cb.activityOut;
121
122        state.label = cb.enabled
123                ? removeTrailingPeriod(cb.enabledDesc)
124                : r.getString(R.string.quick_settings_rssi_emergency_only);
125
126        final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
127                ? cb.signalContentDescription
128                : r.getString(R.string.accessibility_no_signal);
129
130        if (cb.noSim) {
131            state.contentDescription = state.label;
132        } else {
133            String enabledDesc = cb.enabled ? r.getString(R.string.accessibility_cell_data_on)
134                    : r.getString(R.string.accessibility_cell_data_off);
135
136            state.contentDescription = r.getString(
137                    R.string.accessibility_quick_settings_mobile,
138                    enabledDesc, signalContentDesc,
139                    state.label);
140            state.minimalContentDescription = r.getString(
141                    R.string.accessibility_quick_settings_mobile,
142                    r.getString(R.string.accessibility_cell_data), signalContentDesc,
143                    state.label);
144        }
145        state.contentDescription = state.contentDescription + "," + r.getString(
146                R.string.accessibility_quick_settings_open_settings, getTileLabel());
147        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
148                = Button.class.getName();
149        state.value = mDataController.isMobileDataSupported()
150                && mDataController.isMobileDataEnabled();
151    }
152
153    @Override
154    public int getMetricsCategory() {
155        return MetricsEvent.QS_CELLULAR;
156    }
157
158    @Override
159    public boolean isAvailable() {
160        return mController.hasMobileDataFeature();
161    }
162
163    // Remove the period from the network name
164    public static String removeTrailingPeriod(String string) {
165        if (string == null) return null;
166        final int length = string.length();
167        if (string.endsWith(".")) {
168            return string.substring(0, length - 1);
169        }
170        return string;
171    }
172
173    private static final class CallbackInfo {
174        boolean enabled;
175        boolean wifiEnabled;
176        boolean airplaneModeEnabled;
177        int mobileSignalIconId;
178        String signalContentDescription;
179        int dataTypeIconId;
180        String dataContentDescription;
181        boolean activityIn;
182        boolean activityOut;
183        String enabledDesc;
184        boolean noSim;
185        boolean isDataTypeIconWide;
186    }
187
188    private final class CellSignalCallback extends SignalCallbackAdapter {
189        private final CallbackInfo mInfo = new CallbackInfo();
190        @Override
191        public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
192                boolean activityIn, boolean activityOut, String description) {
193            mInfo.wifiEnabled = enabled;
194            refreshState(mInfo);
195        }
196
197        @Override
198        public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
199                int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
200                String description, boolean isWide, int subId) {
201            if (qsIcon == null) {
202                // Not data sim, don't display.
203                return;
204            }
205            mInfo.enabled = qsIcon.visible;
206            mInfo.mobileSignalIconId = qsIcon.icon;
207            mInfo.signalContentDescription = qsIcon.contentDescription;
208            mInfo.dataTypeIconId = qsType;
209            mInfo.dataContentDescription = typeContentDescription;
210            mInfo.activityIn = activityIn;
211            mInfo.activityOut = activityOut;
212            mInfo.enabledDesc = description;
213            mInfo.isDataTypeIconWide = qsType != 0 && isWide;
214            refreshState(mInfo);
215        }
216
217        @Override
218        public void setNoSims(boolean show) {
219            mInfo.noSim = show;
220            if (mInfo.noSim) {
221                // Make sure signal gets cleared out when no sims.
222                mInfo.mobileSignalIconId = 0;
223                mInfo.dataTypeIconId = 0;
224                // Show a No SIMs description to avoid emergency calls message.
225                mInfo.enabled = true;
226                mInfo.enabledDesc = mContext.getString(
227                        R.string.keyguard_missing_sim_message_short);
228                mInfo.signalContentDescription = mInfo.enabledDesc;
229            }
230            refreshState(mInfo);
231        }
232
233        @Override
234        public void setIsAirplaneMode(IconState icon) {
235            mInfo.airplaneModeEnabled = icon.visible;
236            refreshState(mInfo);
237        }
238
239        @Override
240        public void setMobileDataEnabled(boolean enabled) {
241            mDetailAdapter.setMobileDataEnabled(enabled);
242        }
243    };
244
245    private final class CellularDetailAdapter implements DetailAdapter {
246
247        @Override
248        public CharSequence getTitle() {
249            return mContext.getString(R.string.quick_settings_cellular_detail_title);
250        }
251
252        @Override
253        public Boolean getToggleState() {
254            return mDataController.isMobileDataSupported()
255                    ? mDataController.isMobileDataEnabled()
256                    : null;
257        }
258
259        @Override
260        public Intent getSettingsIntent() {
261            return CELLULAR_SETTINGS;
262        }
263
264        @Override
265        public void setToggleState(boolean state) {
266            MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state);
267            mDataController.setMobileDataEnabled(state);
268        }
269
270        @Override
271        public int getMetricsCategory() {
272            return MetricsEvent.QS_DATAUSAGEDETAIL;
273        }
274
275        @Override
276        public View createDetailView(Context context, View convertView, ViewGroup parent) {
277            final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
278                    ? convertView
279                    : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
280            final DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
281            if (info == null) return v;
282            v.bind(info);
283            return v;
284        }
285
286        public void setMobileDataEnabled(boolean enabled) {
287            fireToggleStateChanged(enabled);
288        }
289    }
290}
291