MobileSignalController.java revision 5504d39b7f880fa8b8660e5d4b014ec559124cf9
1da68f596282e60bee832dff07cc96bf64bd15939Jason Monk/*
2da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Copyright (C) 2015 The Android Open Source Project
3da68f596282e60bee832dff07cc96bf64bd15939Jason Monk *
4da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
5da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * you may not use this file except in compliance with the License.
6da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * You may obtain a copy of the License at
7da68f596282e60bee832dff07cc96bf64bd15939Jason Monk *
8da68f596282e60bee832dff07cc96bf64bd15939Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
9da68f596282e60bee832dff07cc96bf64bd15939Jason Monk *
10da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * Unless required by applicable law or agreed to in writing, software
11da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
12da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * See the License for the specific language governing permissions and
14da68f596282e60bee832dff07cc96bf64bd15939Jason Monk * limitations under the License.
15da68f596282e60bee832dff07cc96bf64bd15939Jason Monk */
16da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpackage com.android.systemui.statusbar.policy;
17da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
18da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.content.Context;
19da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.content.Intent;
20da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.net.NetworkCapabilities;
21da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.PhoneStateListener;
22da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.ServiceState;
23da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SignalStrength;
24da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionInfo;
25da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionManager;
26da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.TelephonyManager;
27da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.Log;
28da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.SparseArray;
29da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
30da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.annotations.VisibleForTesting;
31da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.TelephonyIntents;
32da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.cdma.EriInfo;
33da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.R;
34da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
35da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
36da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.SignalCluster;
37da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
38da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.io.PrintWriter;
39da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.util.List;
40da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.util.Objects;
41da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
42da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
43da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpublic class MobileSignalController extends SignalController<
44da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
45da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final TelephonyManager mPhone;
46da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameDefault;
47da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameSeparator;
48da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
49da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final PhoneStateListener mPhoneStateListener;
50da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Save entire info for logging, we only use the id.
51da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final SubscriptionInfo mSubscriptionInfo;
52da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
53da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // @VisibleForDemoMode
54da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final SparseArray<MobileIconGroup> mNetworkToIconLookup;
55da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
56da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Since some pieces of the phone state are interdependent we store it locally,
57da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // this could potentially become part of MobileState for simplification/complication
58da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // of code.
59da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
60da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
61da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private ServiceState mServiceState;
62da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private SignalStrength mSignalStrength;
63da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private MobileIconGroup mDefaultIcons;
64da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private Config mConfig;
65da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
66da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
67da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // need listener lists anymore.
68da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public MobileSignalController(Context context, Config config, boolean hasMobileData,
69da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks,
70da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            List<SignalCluster> signalClusters, NetworkControllerImpl networkController,
71da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            SubscriptionInfo info) {
72da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
73da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                NetworkCapabilities.TRANSPORT_CELLULAR, signalCallbacks, signalClusters,
74da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                networkController);
75da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup = new SparseArray<>();
76da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
77da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone = phone;
78da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mSubscriptionInfo = info;
79da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId());
80da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
81da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameDefault = getStringIfExists(
82da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                com.android.internal.R.string.lockscreen_carrier_default);
83da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
84da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
85da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
86da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault;
875504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        mLastState.networkNameData = mCurrentState.networkNameData = mNetworkNameDefault;
88da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.enabled = mCurrentState.enabled = hasMobileData;
89da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
90da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Get initial data sim state.
91da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateDataSim();
92da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
93da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
94da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setConfiguration(Config config) {
95da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
96da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
97da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateTelephony();
98da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
99da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
100da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public int getDataContentDescription() {
101da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return getIcons().mDataContentDescription;
102da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
103da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
104da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setAirplaneMode(boolean airplaneMode) {
105da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.airplaneMode = airplaneMode;
106da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
107da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
108da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
109da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setInetCondition(int inetCondition, int inetConditionForNetwork) {
110da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // For mobile data, use general inet condition for phone signal indexing,
111da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // and network specific for data indexing (I think this might be a bug, but
112da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // keeping for now).
113da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // TODO: Update with explanation of why.
114da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.inetForNetwork = inetConditionForNetwork;
115da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        setInetCondition(inetCondition);
116da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
117da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
118a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
119a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
120a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        notifyListenersIfNecessary();
121a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
122a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
123da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
124da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Start listening for phone state changes.
125da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
126da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void registerListener() {
127da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener,
128da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                PhoneStateListener.LISTEN_SERVICE_STATE
129da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
130da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_CALL_STATE
131da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
132a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_DATA_ACTIVITY
133a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
134da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
135da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
136da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
137da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Stop listening for phone state changes.
138da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
139da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void unregisterListener() {
140da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener, 0);
141da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
142da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
143da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
144da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Produce a mapping of data network types to icon groups for simple and quick use in
145da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * updateTelephony.
146da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
147da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void mapIconSets() {
148da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.clear();
149da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
150da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
151da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
152da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
153da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
154da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
155da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
156da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (!mConfig.showAtLeast3G) {
157da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
158da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.UNKNOWN);
159da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
160da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
161da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
162da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
163da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.G;
164da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
165da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
166da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
167da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
168da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
169da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
170da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
171da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
172da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
173da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.THREE_G;
174da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
175da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
176da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
177da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.hspaDataDistinguishable) {
178da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            hGroup = TelephonyIcons.H;
179da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
180da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
181da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
182da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
183da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
184da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
185da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.show4gForLte) {
186da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
187da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
188da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
189da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
190da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
191da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
192da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
193da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void notifyListeners() {
194da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup icons = getIcons();
195da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
196da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String contentDescription = getStringIfExists(getContentDescription());
197da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
1985c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
1995c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson        boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
2005c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
2015c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
202da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Only send data sim callbacks to QS.
203da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.dataSim) {
2045c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson            int qsTypeIcon = showDataIcon ? icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
205da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            int length = mSignalsChangedCallbacks.size();
206da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            for (int i = 0; i < length; i++) {
207da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
20849accefb6f42f0aac7fa64faea7dd8856f16171cJason Monk                        && !mCurrentState.isEmergency,
209da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        getQsCurrentIconId(), contentDescription,
210da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        qsTypeIcon,
211a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        mCurrentState.dataConnected
212a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && !mCurrentState.carrierNetworkChangeMode
213a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && mCurrentState.activityIn,
214a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        mCurrentState.dataConnected
215a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && !mCurrentState.carrierNetworkChangeMode
216a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && mCurrentState.activityOut,
217da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        dataContentDescription,
218da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        mCurrentState.isEmergency ? null : mCurrentState.networkName,
219da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        // Only wide if actually showing something.
220da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        icons.mIsWide && qsTypeIcon != 0);
221da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
222da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
223da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int typeIcon = showDataIcon ? icons.mDataType : 0;
224da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int signalClustersLength = mSignalClusters.size();
225da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        for (int i = 0; i < signalClustersLength; i++) {
226da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalClusters.get(i).setMobileDataIndicators(
227da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    mCurrentState.enabled && !mCurrentState.airplaneMode,
228da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    getCurrentIconId(),
229a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    getCurrentDarkIconId(),
230da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    typeIcon,
231da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    contentDescription,
232da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    dataContentDescription,
233da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    // Only wide if actually showing something.
234da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    icons.mIsWide && typeIcon != 0,
235da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    mSubscriptionInfo.getSubscriptionId());
236da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
237da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
238da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
239a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private int getCurrentDarkIconId() {
240a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return getCurrentIconId(false /* light */);
241a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
242a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
243da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
244da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    protected MobileState cleanState() {
245da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return new MobileState();
246da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
247da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
248da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean hasService() {
249da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mServiceState != null) {
250da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // Consider the device to be in service if either voice or data
251da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service is available. Some SIM cards are marketed as data-only
252da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // and do not support voice service, and on these SIM cards, we
253da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // want to show signal bars for data service as well as the "no
254da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service" or "emergency calls only" text that indicates that voice
255da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // is not available.
256da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            switch (mServiceState.getVoiceRegState()) {
257da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_POWER_OFF:
258da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return false;
259da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_OUT_OF_SERVICE:
260da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_EMERGENCY_ONLY:
261da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
262da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                default:
263da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return true;
264da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
265da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
266da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return false;
267da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
268da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
269da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
270da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isCdma() {
271da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mSignalStrength != null) && !mSignalStrength.isGsm();
272da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
273da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
274da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public boolean isEmergencyOnly() {
275da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mServiceState != null && mServiceState.isEmergencyOnly());
276da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
277da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
278da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isRoaming() {
279da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isCdma()) {
280da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            final int iconMode = mServiceState.getCdmaEriIconMode();
281da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
282da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
283da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
284da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
285da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState != null && mServiceState.getRoaming();
286da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
287da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
288da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
289a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private boolean isCarrierNetworkChangeActive() {
290a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return !hasService() && mCurrentState.carrierNetworkChangeMode;
291a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
292a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
293da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void handleBroadcast(Intent intent) {
294da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String action = intent.getAction();
295da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
296da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
297da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
2985504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
299da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
300da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
301da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            notifyListenersIfNecessary();
302da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
303da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateDataSim();
304da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
305da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
306da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
307da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void updateDataSim() {
308da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int defaultDataSub = SubscriptionManager.getDefaultDataSubId();
309da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
310da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
311da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
312da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // There doesn't seem to be a data sim selected, however if
313da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // there isn't a MobileSignalController with dataSim set, then
314da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // QS won't get any callbacks and will be blank.  Instead
315da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // lets just assume we are the data sim (which will basically
316da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // show one at random) in QS until one is selected.  The user
317da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // should pick one soon after, so we shouldn't be in this state
318da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // for long.
319da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = true;
320da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
321da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
322da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
323da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
324da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
325da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the network's name based on incoming spn and plmn.
326da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
3275504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak    void updateNetworkName(boolean showSpn, String spn, String dataSpn,
3285504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            boolean showPlmn, String plmn) {
329da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (CHATTY) {
3305504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
3315504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    + " spn=" + spn + " dataSpn=" + dataSpn
332da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
333da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
334da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        StringBuilder str = new StringBuilder();
3355504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        StringBuilder strData = new StringBuilder();
336da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showPlmn && plmn != null) {
337da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(plmn);
3385504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(plmn);
339da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
340da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showSpn && spn != null) {
341da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (str.length() != 0) {
342da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                str.append(mNetworkNameSeparator);
343da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
344da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(spn);
345da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
346da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (str.length() != 0) {
347da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = str.toString();
348da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
349da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mNetworkNameDefault;
350da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
3515504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (showSpn && dataSpn != null) {
3525504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            if (strData.length() != 0) {
3535504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                strData.append(mNetworkNameSeparator);
3545504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            }
3555504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(dataSpn);
3565504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
3575504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (strData.length() != 0) {
3585504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = strData.toString();
3595504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        } else {
3605504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = mNetworkNameDefault;
3615504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
362da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
363da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
364da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
365da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
366da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * mDataState, and mSimState.  It should be called any time one of these is updated.
367da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * This will call listeners if necessary.
368da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
369da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final void updateTelephony() {
370da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (DEBUG) {
371da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
372da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " ss=" + mSignalStrength);
373da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
374da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.connected = hasService() && mSignalStrength != null;
375da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.connected) {
376da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
377da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getCdmaLevel();
378da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            } else {
379da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getLevel();
380da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
381da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
382da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
383da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
384da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
385da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mDefaultIcons;
386da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
387da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.dataConnected = mCurrentState.connected
388da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mDataState == TelephonyManager.DATA_CONNECTED;
389da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
390a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        if (isCarrierNetworkChangeActive()) {
391a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
392a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        } else if (isRoaming()) {
393da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = TelephonyIcons.ROAMING;
394da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
395da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isEmergencyOnly() != mCurrentState.isEmergency) {
396da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.isEmergency = isEmergencyOnly();
397da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkController.recalculateEmergency();
398da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
399da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Fill in the network name if we think we have it.
400da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
401da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mServiceState.getOperatorAlphaShort() != null) {
402da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
403da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
404a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
405da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
406da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
407da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
408da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
409da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void setActivity(int activity) {
410da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
411da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_IN;
412da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
413da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
414da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
415da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
416da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
417da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
418da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void dump(PrintWriter pw) {
419da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super.dump(pw);
420da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSubscription=" + mSubscriptionInfo + ",");
421da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mServiceState=" + mServiceState + ",");
422da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSignalStrength=" + mSignalStrength + ",");
423da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataState=" + mDataState + ",");
424da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataNetType=" + mDataNetType + ",");
425da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
426da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
427da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    class MobilePhoneStateListener extends PhoneStateListener {
428da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobilePhoneStateListener(int subId) {
429da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super(subId);
430da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
431da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
432da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
433da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
434da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
435da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
436da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
437da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
438da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalStrength = signalStrength;
439da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
440da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
441da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
442da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
443da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onServiceStateChanged(ServiceState state) {
444da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
445da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
446da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " dataState=" + state.getDataRegState());
447da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
448da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mServiceState = state;
449da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
450da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
451da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
452da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
453da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataConnectionStateChanged(int state, int networkType) {
454da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
455da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
456da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " type=" + networkType);
457da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
458da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataState = state;
459da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataNetType = networkType;
460da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
461da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
462da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
463da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
464da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataActivity(int direction) {
465da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
466da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataActivity: direction=" + direction);
467da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
468da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            setActivity(direction);
469da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
470a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
471a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        @Override
472a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public void onCarrierNetworkChange(boolean active) {
473a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            if (DEBUG) {
474a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
475a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            }
476a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.carrierNetworkChangeMode = active;
477a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
478a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            updateTelephony();
479a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
480da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    };
481da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
482da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileIconGroup extends SignalController.IconGroup {
483da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataContentDescription; // mContentDescriptionDataType
484da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataType;
485da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final boolean mIsWide;
486da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int[] mQsDataType;
487da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
488da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
489da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
490da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
491da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int[] qsDataType) {
492a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState,
493a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDiscState, qsDiscState, discContentDesc, dataContentDesc,
494a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    dataType, isWide, qsDataType);
495a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
496a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
497a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public MobileIconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons,
498a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState,
499a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int sbDarkDiscState, int qsDiscState, int discContentDesc, int dataContentDesc,
500a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int dataType, boolean isWide, int[] qsDataType) {
501a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            super(name, sbIcons, sbDarkIcons, qsIcons, contentDesc, sbNullState, qsNullState,
502a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDarkDiscState, qsDiscState, discContentDesc);
503da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataContentDescription = dataContentDesc;
504da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataType = dataType;
505da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mIsWide = isWide;
506da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mQsDataType = qsDataType;
507da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
508da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
509da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
510da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileState extends SignalController.State {
511da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String networkName;
5125504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        String networkNameData;
513da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataSim;
514da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataConnected;
515da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean isEmergency;
516da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean airplaneMode;
517a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        boolean carrierNetworkChangeMode;
518da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int inetForNetwork;
519da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
520da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
521da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void copyFrom(State s) {
522da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.copyFrom(s);
523da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            MobileState state = (MobileState) s;
524da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataSim = state.dataSim;
525da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            networkName = state.networkName;
5265504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            networkNameData = state.networkNameData;
527da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataConnected = state.dataConnected;
528da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            inetForNetwork = state.inetForNetwork;
529da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            isEmergency = state.isEmergency;
530da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            airplaneMode = state.airplaneMode;
531a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
532da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
533da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
534da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
535da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        protected void toString(StringBuilder builder) {
536da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.toString(builder);
537da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append(',');
538da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataSim=").append(dataSim).append(',');
539da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("networkName=").append(networkName).append(',');
5405504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            builder.append("networkNameData=").append(networkNameData).append(',');
541da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataConnected=").append(dataConnected).append(',');
542da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("inetForNetwork=").append(inetForNetwork).append(',');
543da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("isEmergency=").append(isEmergency).append(',');
544a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("airplaneMode=").append(airplaneMode).append(',');
545a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode);
546da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
547da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
548da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
549da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public boolean equals(Object o) {
550da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return super.equals(o)
551da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && Objects.equals(((MobileState) o).networkName, networkName)
5525504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    && Objects.equals(((MobileState) o).networkNameData, networkNameData)
553da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataSim == dataSim
554da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataConnected == dataConnected
555da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).isEmergency == isEmergency
556da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).airplaneMode == airplaneMode
557a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
558da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).inetForNetwork == inetForNetwork;
559da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
560da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
561da68f596282e60bee832dff07cc96bf64bd15939Jason Monk}
562