MobileSignalController.java revision 37d34ba893001d59d0c0a70beea87e00b25e22df
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;
2893fb68fdce8f0d28eaa77704e4b00933260b83ddJason Monkimport android.text.TextUtils;
29da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.Log;
30da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.SparseArray;
31da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
32da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.annotations.VisibleForTesting;
33da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.TelephonyIntents;
34da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.cdma.EriInfo;
35da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.R;
3607b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport com.android.systemui.statusbar.policy.NetworkController.IconState;
37e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monkimport com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
38da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
39c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
40da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
41da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.io.PrintWriter;
4233f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monkimport java.util.BitSet;
43da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.util.Objects;
44da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
45da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
46da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpublic class MobileSignalController extends SignalController<
47da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
48da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final TelephonyManager mPhone;
49c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk    private final SubscriptionDefaults mDefaults;
50da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameDefault;
51da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameSeparator;
52da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
53da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final PhoneStateListener mPhoneStateListener;
54da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Save entire info for logging, we only use the id.
5566845a36c9eeca5296a2bf86793a5d6bedac1b36Jason Monk    final SubscriptionInfo mSubscriptionInfo;
56da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
57da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // @VisibleForDemoMode
58da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final SparseArray<MobileIconGroup> mNetworkToIconLookup;
59da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
60da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Since some pieces of the phone state are interdependent we store it locally,
61da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // this could potentially become part of MobileState for simplification/complication
62da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // of code.
63da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
64da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
65da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private ServiceState mServiceState;
66da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private SignalStrength mSignalStrength;
67da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private MobileIconGroup mDefaultIcons;
68da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private Config mConfig;
69da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
70da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
71da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // need listener lists anymore.
72da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public MobileSignalController(Context context, Config config, boolean hasMobileData,
7307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            TelephonyManager phone, CallbackHandler callbackHandler,
74c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk            NetworkControllerImpl networkController, SubscriptionInfo info,
75c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk            SubscriptionDefaults defaults, Looper receiverLooper) {
76da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
7707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
78da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                networkController);
79da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup = new SparseArray<>();
80da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
81da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone = phone;
82c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk        mDefaults = defaults;
83da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mSubscriptionInfo = info;
8407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
8507b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                receiverLooper);
86da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
87da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameDefault = getStringIfExists(
88da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                com.android.internal.R.string.lockscreen_carrier_default);
89da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
90da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
91da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
9200aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
9300aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk                : mNetworkNameDefault;
9400aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        mLastState.networkName = mCurrentState.networkName = networkName;
9500aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        mLastState.networkNameData = mCurrentState.networkNameData = networkName;
96da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.enabled = mCurrentState.enabled = hasMobileData;
97da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
98da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Get initial data sim state.
99da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateDataSim();
100da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
101da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
102da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setConfiguration(Config config) {
103da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
104da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
105da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateTelephony();
106da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
107da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
108da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public int getDataContentDescription() {
109da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return getIcons().mDataContentDescription;
110da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
111da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
112da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setAirplaneMode(boolean airplaneMode) {
113da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.airplaneMode = airplaneMode;
114da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
115da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
116da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
117fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk    public void setUserSetupComplete(boolean userSetup) {
118fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        mCurrentState.userSetup = userSetup;
119fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        notifyListenersIfNecessary();
120fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk    }
121fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk
12233f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    @Override
12333f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
12433f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isValidated = validatedTransports.get(mTransportType);
12533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.isDefault = connectedTransports.get(mTransportType);
12633f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        // Only show this as not having connectivity if we are default.
12733f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
12833f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        notifyListenersIfNecessary();
129da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
130da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
131a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
132a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
1332fdbe128209f02725c645f29bff941efe865da56Andrew Flynn        updateTelephony();
134a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
135a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
136da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
137da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Start listening for phone state changes.
138da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
139da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void registerListener() {
140da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener,
141da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                PhoneStateListener.LISTEN_SERVICE_STATE
142da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
143da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_CALL_STATE
144da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
145a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_DATA_ACTIVITY
146a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
147da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
148da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
149da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
150da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Stop listening for phone state changes.
151da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
152da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void unregisterListener() {
153da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener, 0);
154da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
155da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
156da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
157da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Produce a mapping of data network types to icon groups for simple and quick use in
158da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * updateTelephony.
159da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
160da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void mapIconSets() {
161da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.clear();
162da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
163da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
164da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
165da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
166da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
167da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
168da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
169da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (!mConfig.showAtLeast3G) {
170da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
171da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.UNKNOWN);
172da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
173da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
174da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
175da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
176da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.G;
177da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
178da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
179da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
180da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
181da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
182da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
183da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
184da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
185da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
186da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.THREE_G;
187da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
188da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
189da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
190da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.hspaDataDistinguishable) {
191da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            hGroup = TelephonyIcons.H;
192da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
193da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
194da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
195da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
196da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
197da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
198da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.show4gForLte) {
199da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
20037d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            if (mConfig.hideLtePlus) {
20137d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
20237d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.FOUR_G);
20337d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            } else {
20437d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
20537d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.FOUR_G_PLUS);
20637d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            }
207da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
208da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
20937d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            if (mConfig.hideLtePlus) {
21037d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
21137d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.LTE);
21237d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            } else {
21337d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
21437d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.LTE_PLUS);
21537d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            }
216da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
2177150d7fa357e00b2904ff3bcf9e06a1014bfbb39Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
218da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
219da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
220da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
221e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk    public void notifyListeners(SignalCallback callback) {
222da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup icons = getIcons();
223da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
224da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String contentDescription = getStringIfExists(getContentDescription());
225da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
226fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
227fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                && mCurrentState.userSetup;
2285c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
229fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        // Show icon in QS when we are connected or need to show roaming or data is disabled.
23033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean showDataIcon = mCurrentState.dataConnected
2311a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
232fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                || dataDisabled;
23307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
23407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                getCurrentIconId(), contentDescription);
23507b75fe65dcb5b8add8246654c65f95f1191933eJason Monk
23607b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        int qsTypeIcon = 0;
23707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState qsIcon = null;
23807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        String description = null;
239da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Only send data sim callbacks to QS.
240da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.dataSim) {
24133f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
24207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            qsIcon = new IconState(mCurrentState.enabled
24307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
24407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
245da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
24607b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityIn = mCurrentState.dataConnected
24707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && !mCurrentState.carrierNetworkChangeMode
24807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && mCurrentState.activityIn;
24907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityOut = mCurrentState.dataConnected
25007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && !mCurrentState.carrierNetworkChangeMode
25107b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                        && mCurrentState.activityOut;
25261633f18611731d7011facbfe3d14f3ec83d86a3Jason Monk        showDataIcon &= mCurrentState.isDefault
2531a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
254fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                || dataDisabled;
255da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int typeIcon = showDataIcon ? icons.mDataType : 0;
256e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
2572fdbe128209f02725c645f29bff941efe865da56Andrew Flynn                activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
2582fdbe128209f02725c645f29bff941efe865da56Andrew Flynn                mSubscriptionInfo.getSubscriptionId());
259a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
260a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
261da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
262da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    protected MobileState cleanState() {
263da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return new MobileState();
264da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
265da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
266da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean hasService() {
267da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mServiceState != null) {
268da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // Consider the device to be in service if either voice or data
269da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service is available. Some SIM cards are marketed as data-only
270da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // and do not support voice service, and on these SIM cards, we
271da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // want to show signal bars for data service as well as the "no
272da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service" or "emergency calls only" text that indicates that voice
273da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // is not available.
274da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            switch (mServiceState.getVoiceRegState()) {
275da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_POWER_OFF:
276da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return false;
277da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_OUT_OF_SERVICE:
278da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_EMERGENCY_ONLY:
279da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
280da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                default:
281da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return true;
282da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
283da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
284da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return false;
285da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
286da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
287da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
288da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isCdma() {
289da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mSignalStrength != null) && !mSignalStrength.isGsm();
290da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
291da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
292da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public boolean isEmergencyOnly() {
293da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mServiceState != null && mServiceState.isEmergencyOnly());
294da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
295da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
296da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isRoaming() {
297da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isCdma()) {
298da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            final int iconMode = mServiceState.getCdmaEriIconMode();
299da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
300da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
301da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
302da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
303da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState != null && mServiceState.getRoaming();
304da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
305da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
306da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
307a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private boolean isCarrierNetworkChangeActive() {
30855fc8004ad1896da615fd08caca87d1b393d085cAndrew Flynn        return mCurrentState.carrierNetworkChangeMode;
309a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
310a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
311da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void handleBroadcast(Intent intent) {
312da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String action = intent.getAction();
313da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
314da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
315da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
3165504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
317da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
318da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
319da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            notifyListenersIfNecessary();
320da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
321da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateDataSim();
3228fcab35828144e27a32a95ed9bd83e4f6d83ac21Jason Monk            notifyListenersIfNecessary();
323da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
324da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
325da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
326da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void updateDataSim() {
327c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk        int defaultDataSub = mDefaults.getDefaultDataSubId();
328da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
329da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
330da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
331da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // There doesn't seem to be a data sim selected, however if
332da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // there isn't a MobileSignalController with dataSim set, then
333da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // QS won't get any callbacks and will be blank.  Instead
334da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // lets just assume we are the data sim (which will basically
335da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // show one at random) in QS until one is selected.  The user
336da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // should pick one soon after, so we shouldn't be in this state
337da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // for long.
338da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = true;
339da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
340da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
341da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
342da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
343da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the network's name based on incoming spn and plmn.
344da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
3455504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak    void updateNetworkName(boolean showSpn, String spn, String dataSpn,
3465504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            boolean showPlmn, String plmn) {
347da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (CHATTY) {
3485504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
3495504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    + " spn=" + spn + " dataSpn=" + dataSpn
350da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
351da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
352da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        StringBuilder str = new StringBuilder();
3535504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        StringBuilder strData = new StringBuilder();
354da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showPlmn && plmn != null) {
355da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(plmn);
3565504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(plmn);
357da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
358da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showSpn && spn != null) {
359da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (str.length() != 0) {
360da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                str.append(mNetworkNameSeparator);
361da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
362da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(spn);
363da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
364da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (str.length() != 0) {
365da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = str.toString();
366da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
367da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mNetworkNameDefault;
368da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
3695504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (showSpn && dataSpn != null) {
3705504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            if (strData.length() != 0) {
3715504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                strData.append(mNetworkNameSeparator);
3725504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            }
3735504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(dataSpn);
3745504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
3755504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (strData.length() != 0) {
3765504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = strData.toString();
3775504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        } else {
3785504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = mNetworkNameDefault;
3795504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
380da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
381da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
382da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
383da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
384da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * mDataState, and mSimState.  It should be called any time one of these is updated.
385da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * This will call listeners if necessary.
386da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
387da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final void updateTelephony() {
388da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (DEBUG) {
389da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
390da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " ss=" + mSignalStrength);
391da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
392da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.connected = hasService() && mSignalStrength != null;
393da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.connected) {
394da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
395da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getCdmaLevel();
396da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            } else {
397da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getLevel();
398da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
399da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
400da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
401da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
402da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
403da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mDefaultIcons;
404da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
405da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.dataConnected = mCurrentState.connected
406da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mDataState == TelephonyManager.DATA_CONNECTED;
407da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
408a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        if (isCarrierNetworkChangeActive()) {
409a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
410a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        } else if (isRoaming()) {
411da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = TelephonyIcons.ROAMING;
4121a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk        } else if (isDataDisabled()) {
4131a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
414da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
415da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isEmergencyOnly() != mCurrentState.isEmergency) {
416da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.isEmergency = isEmergencyOnly();
417da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkController.recalculateEmergency();
418da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
419da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Fill in the network name if we think we have it.
420da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
42193fb68fdce8f0d28eaa77704e4b00933260b83ddJason Monk                && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
422da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
423da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
424a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
425da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
426da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
427da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
4281a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk    private boolean isDataDisabled() {
4291a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk        return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId());
4301a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk    }
4311a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk
432da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
433da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void setActivity(int activity) {
434da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
435da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_IN;
436da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
437da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
438da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
439da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
440da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
441da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
442da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void dump(PrintWriter pw) {
443da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super.dump(pw);
444da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSubscription=" + mSubscriptionInfo + ",");
445da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mServiceState=" + mServiceState + ",");
446da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSignalStrength=" + mSignalStrength + ",");
447da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataState=" + mDataState + ",");
448da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataNetType=" + mDataNetType + ",");
449da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
450da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
451da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    class MobilePhoneStateListener extends PhoneStateListener {
45207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        public MobilePhoneStateListener(int subId, Looper looper) {
45307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            super(subId, looper);
454da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
455da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
456da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
457da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
458da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
459da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
460da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
461da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
462da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalStrength = signalStrength;
463da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
464da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
465da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
466da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
467da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onServiceStateChanged(ServiceState state) {
468da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
469da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
470da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " dataState=" + state.getDataRegState());
471da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
472da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mServiceState = state;
47367b2c16a9a9060d37888bdab4dfadd384a76e9d7Jason Monk            mDataNetType = state.getDataNetworkType();
474da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
475da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
476da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
477da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
478da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataConnectionStateChanged(int state, int networkType) {
479da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
480da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
481da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " type=" + networkType);
482da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
483da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataState = state;
484da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataNetType = networkType;
485da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
486da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
487da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
488da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
489da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataActivity(int direction) {
490da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
491da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataActivity: direction=" + direction);
492da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
493da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            setActivity(direction);
494da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
495a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
496a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        @Override
497a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public void onCarrierNetworkChange(boolean active) {
498a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            if (DEBUG) {
499a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
500a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            }
501a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.carrierNetworkChangeMode = active;
502a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
503a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            updateTelephony();
504a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
505da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    };
506da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
507da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileIconGroup extends SignalController.IconGroup {
508da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataContentDescription; // mContentDescriptionDataType
509da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataType;
510da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final boolean mIsWide;
51133f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        final int mQsDataType;
512da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
513da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
514da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
515da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
51633f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                int qsDataType) {
5172fdbe128209f02725c645f29bff941efe865da56Andrew Flynn            super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
5182fdbe128209f02725c645f29bff941efe865da56Andrew Flynn                    qsDiscState, discContentDesc);
519da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataContentDescription = dataContentDesc;
520da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataType = dataType;
521da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mIsWide = isWide;
522da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mQsDataType = qsDataType;
523da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
524da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
525da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
526da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileState extends SignalController.State {
527da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String networkName;
5285504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        String networkNameData;
529da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataSim;
530da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataConnected;
531da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean isEmergency;
532da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean airplaneMode;
533a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        boolean carrierNetworkChangeMode;
53433f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isDefault;
535fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        boolean userSetup;
536da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
537da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
538da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void copyFrom(State s) {
539da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.copyFrom(s);
540da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            MobileState state = (MobileState) s;
541da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataSim = state.dataSim;
542da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            networkName = state.networkName;
5435504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            networkNameData = state.networkNameData;
544da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataConnected = state.dataConnected;
54533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            isDefault = state.isDefault;
546da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            isEmergency = state.isEmergency;
547da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            airplaneMode = state.airplaneMode;
548a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
549fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            userSetup = state.userSetup;
550da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
551da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
552da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
553da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        protected void toString(StringBuilder builder) {
554da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.toString(builder);
555da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append(',');
556da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataSim=").append(dataSim).append(',');
557da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("networkName=").append(networkName).append(',');
5585504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            builder.append("networkNameData=").append(networkNameData).append(',');
559da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataConnected=").append(dataConnected).append(',');
56033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            builder.append("isDefault=").append(isDefault).append(',');
561da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("isEmergency=").append(isEmergency).append(',');
562a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("airplaneMode=").append(airplaneMode).append(',');
563fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
564fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                    .append(',');
565fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            builder.append("userSetup=").append(userSetup);
566da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
567da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
568da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
569da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public boolean equals(Object o) {
570da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return super.equals(o)
571da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && Objects.equals(((MobileState) o).networkName, networkName)
5725504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    && Objects.equals(((MobileState) o).networkNameData, networkNameData)
573da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataSim == dataSim
574da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataConnected == dataConnected
575da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).isEmergency == isEmergency
576da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).airplaneMode == airplaneMode
577a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
578fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                    && ((MobileState) o).userSetup == userSetup
57933f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                    && ((MobileState) o).isDefault == isDefault;
580da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
581da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
582da68f596282e60bee832dff07cc96bf64bd15939Jason Monk}
583