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