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