MobileSignalController.java revision 33f8ae7543fbf7d94266f0f1621ec873aa2542f1
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;
2107b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport android.os.Looper;
22da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.PhoneStateListener;
23da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.ServiceState;
24da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SignalStrength;
25da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionInfo;
26da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionManager;
27da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.TelephonyManager;
28da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.Log;
29da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.SparseArray;
30da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
31da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.annotations.VisibleForTesting;
32da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.TelephonyIntents;
33da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.cdma.EriInfo;
34da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.R;
3507b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport com.android.systemui.statusbar.policy.NetworkController.IconState;
36da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
37da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
38da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.io.PrintWriter;
3933f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monkimport java.util.BitSet;
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,
6907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            TelephonyManager phone, CallbackHandler callbackHandler,
7007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            NetworkControllerImpl networkController, SubscriptionInfo info, Looper receiverLooper) {
71da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
7207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
73da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                networkController);
74da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup = new SparseArray<>();
75da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
76da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone = phone;
77da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mSubscriptionInfo = info;
7807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
7907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                receiverLooper);
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
10933f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    @Override
11033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
11133f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isValidated = validatedTransports.get(mTransportType);
11233f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.isDefault = connectedTransports.get(mTransportType);
11333f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        // Only show this as not having connectivity if we are default.
11433f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
11533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        notifyListenersIfNecessary();
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
19933f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        // Show icon in QS when we are connected or need to show roaming.
20033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean showDataIcon = mCurrentState.dataConnected
2015c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson                || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
20207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
20307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                getCurrentIconId(), contentDescription);
20407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk
20507b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        int qsTypeIcon = 0;
20607b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState qsIcon = null;
20707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        String description = null;
208da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Only send data sim callbacks to QS.
209da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.dataSim) {
21033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
21107b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            qsIcon = new IconState(mCurrentState.enabled
21207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
21307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
214da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
21507b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityIn = mCurrentState.dataConnected
21607b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && !mCurrentState.carrierNetworkChangeMode
21707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && mCurrentState.activityIn;
21807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityOut = mCurrentState.dataConnected
21907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && !mCurrentState.carrierNetworkChangeMode
22007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && mCurrentState.activityOut;
22133f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        showDataIcon &= mCurrentState.isDefault;
222da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int typeIcon = showDataIcon ? icons.mDataType : 0;
22307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, getCurrentDarkIconId(),
22407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                typeIcon, qsTypeIcon, activityIn, activityOut, dataContentDescription, description,
22507b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                icons.mIsWide, mSubscriptionInfo.getSubscriptionId());
226da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
227da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
228a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private int getCurrentDarkIconId() {
229a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return getCurrentIconId(false /* light */);
230a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
231a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
232da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
233da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    protected MobileState cleanState() {
234da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return new MobileState();
235da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
236da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
237da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean hasService() {
238da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mServiceState != null) {
239da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // Consider the device to be in service if either voice or data
240da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service is available. Some SIM cards are marketed as data-only
241da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // and do not support voice service, and on these SIM cards, we
242da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // want to show signal bars for data service as well as the "no
243da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service" or "emergency calls only" text that indicates that voice
244da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // is not available.
245da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            switch (mServiceState.getVoiceRegState()) {
246da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_POWER_OFF:
247da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return false;
248da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_OUT_OF_SERVICE:
249da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_EMERGENCY_ONLY:
250da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
251da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                default:
252da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return true;
253da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
254da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
255da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return false;
256da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
257da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
258da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
259da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isCdma() {
260da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mSignalStrength != null) && !mSignalStrength.isGsm();
261da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
262da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
263da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public boolean isEmergencyOnly() {
264da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mServiceState != null && mServiceState.isEmergencyOnly());
265da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
266da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
267da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isRoaming() {
268da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isCdma()) {
269da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            final int iconMode = mServiceState.getCdmaEriIconMode();
270da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
271da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
272da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
273da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
274da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState != null && mServiceState.getRoaming();
275da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
276da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
277da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
278a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private boolean isCarrierNetworkChangeActive() {
279a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        return !hasService() && mCurrentState.carrierNetworkChangeMode;
280a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
281a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
282da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void handleBroadcast(Intent intent) {
283da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String action = intent.getAction();
284da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
285da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
286da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
2875504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
288da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
289da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
290da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            notifyListenersIfNecessary();
291da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
292da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateDataSim();
293da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
294da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
295da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
296da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void updateDataSim() {
297da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int defaultDataSub = SubscriptionManager.getDefaultDataSubId();
298da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
299da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
300da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
301da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // There doesn't seem to be a data sim selected, however if
302da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // there isn't a MobileSignalController with dataSim set, then
303da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // QS won't get any callbacks and will be blank.  Instead
304da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // lets just assume we are the data sim (which will basically
305da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // show one at random) in QS until one is selected.  The user
306da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // should pick one soon after, so we shouldn't be in this state
307da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // for long.
308da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = true;
309da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
310da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
311da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
312da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
313da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
314da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the network's name based on incoming spn and plmn.
315da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
3165504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak    void updateNetworkName(boolean showSpn, String spn, String dataSpn,
3175504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            boolean showPlmn, String plmn) {
318da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (CHATTY) {
3195504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
3205504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    + " spn=" + spn + " dataSpn=" + dataSpn
321da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
322da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
323da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        StringBuilder str = new StringBuilder();
3245504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        StringBuilder strData = new StringBuilder();
325da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showPlmn && plmn != null) {
326da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(plmn);
3275504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(plmn);
328da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
329da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showSpn && spn != null) {
330da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (str.length() != 0) {
331da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                str.append(mNetworkNameSeparator);
332da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
333da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(spn);
334da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
335da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (str.length() != 0) {
336da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = str.toString();
337da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
338da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mNetworkNameDefault;
339da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
3405504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (showSpn && dataSpn != null) {
3415504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            if (strData.length() != 0) {
3425504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                strData.append(mNetworkNameSeparator);
3435504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            }
3445504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(dataSpn);
3455504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
3465504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (strData.length() != 0) {
3475504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = strData.toString();
3485504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        } else {
3495504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = mNetworkNameDefault;
3505504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
351da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
352da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
353da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
354da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
355da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * mDataState, and mSimState.  It should be called any time one of these is updated.
356da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * This will call listeners if necessary.
357da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
358da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final void updateTelephony() {
359da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (DEBUG) {
360da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
361da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " ss=" + mSignalStrength);
362da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
363da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.connected = hasService() && mSignalStrength != null;
364da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.connected) {
365da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
366da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getCdmaLevel();
367da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            } else {
368da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getLevel();
369da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
370da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
371da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
372da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
373da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
374da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mDefaultIcons;
375da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
376da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.dataConnected = mCurrentState.connected
377da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mDataState == TelephonyManager.DATA_CONNECTED;
378da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
379a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        if (isCarrierNetworkChangeActive()) {
380a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
381a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        } else if (isRoaming()) {
382da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = TelephonyIcons.ROAMING;
383da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
384da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isEmergencyOnly() != mCurrentState.isEmergency) {
385da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.isEmergency = isEmergencyOnly();
386da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkController.recalculateEmergency();
387da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
388da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Fill in the network name if we think we have it.
389da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
390da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mServiceState.getOperatorAlphaShort() != null) {
391da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
392da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
393a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
394da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
395da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
396da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
397da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
398da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void setActivity(int activity) {
399da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
400da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_IN;
401da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
402da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
403da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
404da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
405da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
406da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
407da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void dump(PrintWriter pw) {
408da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super.dump(pw);
409da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSubscription=" + mSubscriptionInfo + ",");
410da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mServiceState=" + mServiceState + ",");
411da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSignalStrength=" + mSignalStrength + ",");
412da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataState=" + mDataState + ",");
413da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataNetType=" + mDataNetType + ",");
414da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
415da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
416da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    class MobilePhoneStateListener extends PhoneStateListener {
41707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        public MobilePhoneStateListener(int subId, Looper looper) {
41807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            super(subId, looper);
419da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
420da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
421da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
422da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
423da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
424da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
425da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
426da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
427da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalStrength = signalStrength;
428da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
429da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
430da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
431da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
432da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onServiceStateChanged(ServiceState state) {
433da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
434da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
435da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " dataState=" + state.getDataRegState());
436da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
437da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mServiceState = state;
438da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
439da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
440da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
441da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
442da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataConnectionStateChanged(int state, int networkType) {
443da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
444da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
445da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " type=" + networkType);
446da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
447da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataState = state;
448da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataNetType = networkType;
449da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
450da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
451da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
452da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
453da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataActivity(int direction) {
454da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
455da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataActivity: direction=" + direction);
456da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
457da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            setActivity(direction);
458da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
459a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
460a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        @Override
461a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public void onCarrierNetworkChange(boolean active) {
462a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            if (DEBUG) {
463a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
464a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            }
465a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.carrierNetworkChangeMode = active;
466a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
467a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            updateTelephony();
468a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
469da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    };
470da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
471da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileIconGroup extends SignalController.IconGroup {
472da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataContentDescription; // mContentDescriptionDataType
473da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataType;
474da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final boolean mIsWide;
47533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        final int mQsDataType;
476da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
477da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
478da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
479da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
48033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                int qsDataType) {
481a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState,
482a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDiscState, qsDiscState, discContentDesc, dataContentDesc,
483a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    dataType, isWide, qsDataType);
484a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
485a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
486a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public MobileIconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons,
487a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState,
488a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                int sbDarkDiscState, int qsDiscState, int discContentDesc, int dataContentDesc,
48933f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                int dataType, boolean isWide, int qsDataType) {
490a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            super(name, sbIcons, sbDarkIcons, qsIcons, contentDesc, sbNullState, qsNullState,
491a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    sbDiscState, sbDarkDiscState, qsDiscState, discContentDesc);
492da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataContentDescription = dataContentDesc;
493da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataType = dataType;
494da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mIsWide = isWide;
495da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mQsDataType = qsDataType;
496da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
497da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
498da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
499da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileState extends SignalController.State {
500da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String networkName;
5015504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        String networkNameData;
502da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataSim;
503da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataConnected;
504da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean isEmergency;
505da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean airplaneMode;
506a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        boolean carrierNetworkChangeMode;
50733f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isDefault;
508da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
509da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
510da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void copyFrom(State s) {
511da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.copyFrom(s);
512da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            MobileState state = (MobileState) s;
513da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataSim = state.dataSim;
514da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            networkName = state.networkName;
5155504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            networkNameData = state.networkNameData;
516da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataConnected = state.dataConnected;
51733f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            isDefault = state.isDefault;
518da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            isEmergency = state.isEmergency;
519da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            airplaneMode = state.airplaneMode;
520a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
521da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
522da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
523da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
524da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        protected void toString(StringBuilder builder) {
525da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.toString(builder);
526da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append(',');
527da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataSim=").append(dataSim).append(',');
528da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("networkName=").append(networkName).append(',');
5295504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            builder.append("networkNameData=").append(networkNameData).append(',');
530da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataConnected=").append(dataConnected).append(',');
53133f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            builder.append("isDefault=").append(isDefault).append(',');
532da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("isEmergency=").append(isEmergency).append(',');
533a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("airplaneMode=").append(airplaneMode).append(',');
534a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode);
535da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
536da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
537da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
538da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public boolean equals(Object o) {
539da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return super.equals(o)
540da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && Objects.equals(((MobileState) o).networkName, networkName)
5415504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    && Objects.equals(((MobileState) o).networkNameData, networkNameData)
542da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataSim == dataSim
543da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataConnected == dataConnected
544da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).isEmergency == isEmergency
545da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).airplaneMode == airplaneMode
546a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
54733f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                    && ((MobileState) o).isDefault == isDefault;
548da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
549da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
550da68f596282e60bee832dff07cc96bf64bd15939Jason Monk}
551