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