MobileSignalController.java revision a478d70a68696380acbd4a9739dfaaebff61c728
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;
87da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.enabled = mCurrentState.enabled = hasMobileData;
88da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
89da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Get initial data sim state.
90da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateDataSim();
91da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
92da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
93da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setConfiguration(Config config) {
94da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
95da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
96da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateTelephony();
97da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
98da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
99da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public int getDataContentDescription() {
100da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return getIcons().mDataContentDescription;
101da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
102da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
103da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setAirplaneMode(boolean airplaneMode) {
104da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.airplaneMode = airplaneMode;
105da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
106da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
107da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
108da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setInetCondition(int inetCondition, int inetConditionForNetwork) {
109da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // For mobile data, use general inet condition for phone signal indexing,
110da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // and network specific for data indexing (I think this might be a bug, but
111da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // keeping for now).
112da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // TODO: Update with explanation of why.
113da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.inetForNetwork = inetConditionForNetwork;
114da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        setInetCondition(inetCondition);
115da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
116da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
117a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
118a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
119a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        notifyListenersIfNecessary();
120a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
121a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
122da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
123da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Start listening for phone state changes.
124da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
125da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void registerListener() {
126da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener,
127da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                PhoneStateListener.LISTEN_SERVICE_STATE
128da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
129da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_CALL_STATE
130da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
131a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_DATA_ACTIVITY
132a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
133da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
134da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
135da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
136da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Stop listening for phone state changes.
137da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
138da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void unregisterListener() {
139da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener, 0);
140da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
141da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
142da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
143da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Produce a mapping of data network types to icon groups for simple and quick use in
144da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * updateTelephony.
145da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
146da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void mapIconSets() {
147da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.clear();
148da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
149da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
150da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
151da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
152da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
153da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
154da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
155da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (!mConfig.showAtLeast3G) {
156da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
157da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.UNKNOWN);
158da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
159da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
160da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
161da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
162da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.G;
163da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
164da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
165da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
166da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
167da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
168da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
169da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
170da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
171da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
172da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.THREE_G;
173da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
174da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
175da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
176da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.hspaDataDistinguishable) {
177da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            hGroup = TelephonyIcons.H;
178da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
179da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
180da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
181da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
182da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
183da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
184da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.show4gForLte) {
185da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
186da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
187da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
188da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
189da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
190da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
191da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
192da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void notifyListeners() {
193da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup icons = getIcons();
194da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
195da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String contentDescription = getStringIfExists(getContentDescription());
196da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
1975c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
1985c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson        boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0
1995c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
2005c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
201da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Only send data sim callbacks to QS.
202da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.dataSim) {
2035c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson            int qsTypeIcon = showDataIcon ? icons.mQsDataType[mCurrentState.inetForNetwork] : 0;
204da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            int length = mSignalsChangedCallbacks.size();
205da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            for (int i = 0; i < length; i++) {
206da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
20749accefb6f42f0aac7fa64faea7dd8856f16171cJason Monk                        && !mCurrentState.isEmergency,
208da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        getQsCurrentIconId(), contentDescription,
209da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        qsTypeIcon,
210a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        mCurrentState.dataConnected
211a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && !mCurrentState.carrierNetworkChangeMode
212a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && mCurrentState.activityIn,
213a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        mCurrentState.dataConnected
214a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && !mCurrentState.carrierNetworkChangeMode
215a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                            && mCurrentState.activityOut,
216da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        dataContentDescription,
217da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        mCurrentState.isEmergency ? null : mCurrentState.networkName,
218da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        // Only wide if actually showing something.
219da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        icons.mIsWide && qsTypeIcon != 0);
220da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
221da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
222da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int typeIcon = showDataIcon ? icons.mDataType : 0;
223da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int signalClustersLength = mSignalClusters.size();
224da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        for (int i = 0; i < signalClustersLength; i++) {
225da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalClusters.get(i).setMobileDataIndicators(
226da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    mCurrentState.enabled && !mCurrentState.airplaneMode,
227da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    getCurrentIconId(),
228a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    getCurrentDarkIconId(),
229da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    typeIcon,
230da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    contentDescription,
231da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    dataContentDescription,
232da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    // Only wide if actually showing something.
233da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    icons.mIsWide && typeIcon != 0,
234da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    mSubscriptionInfo.getSubscriptionId());
235da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
236da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
237da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
238a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private int getCurrentDarkIconId() {
239a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return getCurrentIconId(false /* light */);
240a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
241a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
242da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
243da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    protected MobileState cleanState() {
244da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return new MobileState();
245da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
246da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
247da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean hasService() {
248da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mServiceState != null) {
249da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // Consider the device to be in service if either voice or data
250da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service is available. Some SIM cards are marketed as data-only
251da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // and do not support voice service, and on these SIM cards, we
252da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // want to show signal bars for data service as well as the "no
253da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service" or "emergency calls only" text that indicates that voice
254da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // is not available.
255da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            switch (mServiceState.getVoiceRegState()) {
256da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_POWER_OFF:
257da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return false;
258da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_OUT_OF_SERVICE:
259da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_EMERGENCY_ONLY:
260da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
261da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                default:
262da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return true;
263da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
264da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
265da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return false;
266da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
267da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
268da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
269da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isCdma() {
270da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mSignalStrength != null) && !mSignalStrength.isGsm();
271da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
272da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
273da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public boolean isEmergencyOnly() {
274da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mServiceState != null && mServiceState.isEmergencyOnly());
275da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
276da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
277da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isRoaming() {
278da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isCdma()) {
279da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            final int iconMode = mServiceState.getCdmaEriIconMode();
280da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
281da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
282da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
283da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
284da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState != null && mServiceState.getRoaming();
285da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
286da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
287da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
288a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private boolean isCarrierNetworkChangeActive() {
289a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return !hasService() && mCurrentState.carrierNetworkChangeMode;
290a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
291a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
292da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void handleBroadcast(Intent intent) {
293da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String action = intent.getAction();
294da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
295da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
296da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
297da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
298da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
299da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            notifyListenersIfNecessary();
300da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
301da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateDataSim();
302da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
303da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
304da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
305da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void updateDataSim() {
306da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int defaultDataSub = SubscriptionManager.getDefaultDataSubId();
307da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
308da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
309da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
310da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // There doesn't seem to be a data sim selected, however if
311da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // there isn't a MobileSignalController with dataSim set, then
312da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // QS won't get any callbacks and will be blank.  Instead
313da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // lets just assume we are the data sim (which will basically
314da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // show one at random) in QS until one is selected.  The user
315da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // should pick one soon after, so we shouldn't be in this state
316da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // for long.
317da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = true;
318da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
319da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
320da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
321da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
322da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
323da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the network's name based on incoming spn and plmn.
324da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
325da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
326da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (CHATTY) {
327da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
328da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
329da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
330da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        StringBuilder str = new StringBuilder();
331da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showPlmn && plmn != null) {
332da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(plmn);
333da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
334da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showSpn && spn != null) {
335da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (str.length() != 0) {
336da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                str.append(mNetworkNameSeparator);
337da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
338da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(spn);
339da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
340da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (str.length() != 0) {
341da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = str.toString();
342da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
343da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mNetworkNameDefault;
344da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
345da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
346da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
347da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
348da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
349da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * mDataState, and mSimState.  It should be called any time one of these is updated.
350da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * This will call listeners if necessary.
351da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
352da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final void updateTelephony() {
353da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (DEBUG) {
354da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
355da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " ss=" + mSignalStrength);
356da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
357da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.connected = hasService() && mSignalStrength != null;
358da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.connected) {
359da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
360da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getCdmaLevel();
361da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            } else {
362da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getLevel();
363da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
364da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
365da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
366da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
367da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
368da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mDefaultIcons;
369da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
370da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.dataConnected = mCurrentState.connected
371da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mDataState == TelephonyManager.DATA_CONNECTED;
372da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
373a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        if (isCarrierNetworkChangeActive()) {
374a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
375a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        } else if (isRoaming()) {
376da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = TelephonyIcons.ROAMING;
377da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
378da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isEmergencyOnly() != mCurrentState.isEmergency) {
379da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.isEmergency = isEmergencyOnly();
380da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkController.recalculateEmergency();
381da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
382da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Fill in the network name if we think we have it.
383da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
384da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mServiceState.getOperatorAlphaShort() != null) {
385da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
386da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
387a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
388da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
389da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
390da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
391da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
392da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void setActivity(int activity) {
393da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
394da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_IN;
395da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
396da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
397da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
398da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
399da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
400da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
401da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void dump(PrintWriter pw) {
402da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super.dump(pw);
403da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSubscription=" + mSubscriptionInfo + ",");
404da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mServiceState=" + mServiceState + ",");
405da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSignalStrength=" + mSignalStrength + ",");
406da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataState=" + mDataState + ",");
407da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataNetType=" + mDataNetType + ",");
408da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
409da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
410da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    class MobilePhoneStateListener extends PhoneStateListener {
411da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobilePhoneStateListener(int subId) {
412da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super(subId);
413da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
414da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
415da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
416da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
417da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
418da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
419da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
420da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
421da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalStrength = signalStrength;
422da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
423da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
424da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
425da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
426da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onServiceStateChanged(ServiceState state) {
427da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
428da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
429da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " dataState=" + state.getDataRegState());
430da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
431da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mServiceState = state;
432da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
433da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
434da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
435da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
436da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataConnectionStateChanged(int state, int networkType) {
437da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
438da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
439da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " type=" + networkType);
440da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
441da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataState = state;
442da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataNetType = networkType;
443da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
444da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
445da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
446da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
447da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataActivity(int direction) {
448da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
449da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataActivity: direction=" + direction);
450da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
451da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            setActivity(direction);
452da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
453a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
454a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        @Override
455a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public void onCarrierNetworkChange(boolean active) {
456a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            if (DEBUG) {
457a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
458a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            }
459a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.carrierNetworkChangeMode = active;
460a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
461a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            updateTelephony();
462a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
463da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    };
464da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
465da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileIconGroup extends SignalController.IconGroup {
466da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataContentDescription; // mContentDescriptionDataType
467da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataType;
468da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final boolean mIsWide;
469da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int[] mQsDataType;
470da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
471da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
472da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
473da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
474da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int[] qsDataType) {
475a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState,
476a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDiscState, qsDiscState, discContentDesc, dataContentDesc,
477a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    dataType, isWide, qsDataType);
478a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
479a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
480a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public MobileIconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons,
481a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState,
482a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int sbDarkDiscState, int qsDiscState, int discContentDesc, int dataContentDesc,
483a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int dataType, boolean isWide, int[] qsDataType) {
484a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            super(name, sbIcons, sbDarkIcons, qsIcons, contentDesc, sbNullState, qsNullState,
485a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDarkDiscState, qsDiscState, discContentDesc);
486da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataContentDescription = dataContentDesc;
487da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataType = dataType;
488da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mIsWide = isWide;
489da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mQsDataType = qsDataType;
490da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
491da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
492da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
493da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileState extends SignalController.State {
494da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String networkName;
495da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataSim;
496da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataConnected;
497da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean isEmergency;
498da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean airplaneMode;
499a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        boolean carrierNetworkChangeMode;
500da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int inetForNetwork;
501da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
502da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
503da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void copyFrom(State s) {
504da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.copyFrom(s);
505da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            MobileState state = (MobileState) s;
506da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataSim = state.dataSim;
507da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            networkName = state.networkName;
508da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataConnected = state.dataConnected;
509da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            inetForNetwork = state.inetForNetwork;
510da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            isEmergency = state.isEmergency;
511da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            airplaneMode = state.airplaneMode;
512a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
513da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
514da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
515da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
516da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        protected void toString(StringBuilder builder) {
517da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.toString(builder);
518da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append(',');
519da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataSim=").append(dataSim).append(',');
520da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("networkName=").append(networkName).append(',');
521da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataConnected=").append(dataConnected).append(',');
522da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("inetForNetwork=").append(inetForNetwork).append(',');
523da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("isEmergency=").append(isEmergency).append(',');
524a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("airplaneMode=").append(airplaneMode).append(',');
525a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode);
526da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
527da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
528da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
529da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public boolean equals(Object o) {
530da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return super.equals(o)
531da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && Objects.equals(((MobileState) o).networkName, networkName)
532da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataSim == dataSim
533da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataConnected == dataConnected
534da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).isEmergency == isEmergency
535da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).airplaneMode == airplaneMode
536a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
537da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).inetForNetwork == inetForNetwork;
538da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
539da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
540da68f596282e60bee832dff07cc96bf64bd15939Jason Monk}
541