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