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