MobileSignalController.java revision 0288de0e5635b714273ff8185b4bdbfb9ece447c
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;
200288de0e5635b714273ff8185b4bdbfb9ece447cJason Monkimport android.database.ContentObserver;
21da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.net.NetworkCapabilities;
220288de0e5635b714273ff8185b4bdbfb9ece447cJason Monkimport android.os.Handler;
2307b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport android.os.Looper;
240288de0e5635b714273ff8185b4bdbfb9ece447cJason Monkimport android.provider.Settings.Global;
25da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.PhoneStateListener;
26da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.ServiceState;
27da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SignalStrength;
28da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionInfo;
29da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.SubscriptionManager;
30da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.telephony.TelephonyManager;
3193fb68fdce8f0d28eaa77704e4b00933260b83ddJason Monkimport android.text.TextUtils;
32da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.Log;
33da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport android.util.SparseArray;
34da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
35da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.annotations.VisibleForTesting;
36da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.TelephonyIntents;
37da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.internal.telephony.cdma.EriInfo;
38da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.R;
3907b75fe65dcb5b8add8246654c65f95f1191933eJason Monkimport com.android.systemui.statusbar.policy.NetworkController.IconState;
40e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monkimport com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
41da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
42c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monkimport com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
43da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
44da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.io.PrintWriter;
4533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monkimport java.util.BitSet;
46da68f596282e60bee832dff07cc96bf64bd15939Jason Monkimport java.util.Objects;
47da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
48da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
49da68f596282e60bee832dff07cc96bf64bd15939Jason Monkpublic class MobileSignalController extends SignalController<
50da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
51da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final TelephonyManager mPhone;
52c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk    private final SubscriptionDefaults mDefaults;
53da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameDefault;
54da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final String mNetworkNameSeparator;
550288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk    private final ContentObserver mObserver;
56da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
57da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final PhoneStateListener mPhoneStateListener;
58da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Save entire info for logging, we only use the id.
5966845a36c9eeca5296a2bf86793a5d6bedac1b36Jason Monk    final SubscriptionInfo mSubscriptionInfo;
60da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
61da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // @VisibleForDemoMode
62da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    final SparseArray<MobileIconGroup> mNetworkToIconLookup;
63da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
64da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // Since some pieces of the phone state are interdependent we store it locally,
65da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // this could potentially become part of MobileState for simplification/complication
66da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // of code.
67da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
68da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
69da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private ServiceState mServiceState;
70da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private SignalStrength mSignalStrength;
71da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private MobileIconGroup mDefaultIcons;
72da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private Config mConfig;
73da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
74da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
75da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    // need listener lists anymore.
76da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public MobileSignalController(Context context, Config config, boolean hasMobileData,
7707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            TelephonyManager phone, CallbackHandler callbackHandler,
78c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk            NetworkControllerImpl networkController, SubscriptionInfo info,
79c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk            SubscriptionDefaults defaults, Looper receiverLooper) {
80da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
8107b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
82da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                networkController);
83da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup = new SparseArray<>();
84da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
85da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone = phone;
86c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk        mDefaults = defaults;
87da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mSubscriptionInfo = info;
8807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(),
8907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                receiverLooper);
90da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
91da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkNameDefault = getStringIfExists(
92da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                com.android.internal.R.string.lockscreen_carrier_default);
93da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
94da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
95da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
9600aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
9700aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk                : mNetworkNameDefault;
9800aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        mLastState.networkName = mCurrentState.networkName = networkName;
9900aa9d4427cd6ca00edcbc1b7915bc22ac580d6aJason Monk        mLastState.networkNameData = mCurrentState.networkNameData = networkName;
100da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.enabled = mCurrentState.enabled = hasMobileData;
101da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
102da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Get initial data sim state.
103da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateDataSim();
1040288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk        mObserver = new ContentObserver(new Handler(receiverLooper)) {
1050288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk            @Override
1060288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk            public void onChange(boolean selfChange) {
1070288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                updateTelephony();
1080288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk            }
1090288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk        };
110da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
111da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
112da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setConfiguration(Config config) {
113da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mConfig = config;
114da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mapIconSets();
115da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        updateTelephony();
116da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
117da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
118da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public int getDataContentDescription() {
119da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return getIcons().mDataContentDescription;
120da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
121da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
122da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void setAirplaneMode(boolean airplaneMode) {
123da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.airplaneMode = airplaneMode;
124da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
125da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
126da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
127fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk    public void setUserSetupComplete(boolean userSetup) {
128fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        mCurrentState.userSetup = userSetup;
129fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        notifyListenersIfNecessary();
130fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk    }
131fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk
13233f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    @Override
13333f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk    public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
13433f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isValidated = validatedTransports.get(mTransportType);
13533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.isDefault = connectedTransports.get(mTransportType);
13633f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        // Only show this as not having connectivity if we are default.
13733f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        mCurrentState.inetCondition = (isValidated || !mCurrentState.isDefault) ? 1 : 0;
13833f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        notifyListenersIfNecessary();
139da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
140da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
141a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) {
142a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode;
1432fdbe128209f02725c645f29bff941efe865da56Andrew Flynn        updateTelephony();
144a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
145a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
146da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
147da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Start listening for phone state changes.
148da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
149da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void registerListener() {
150da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener,
151da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                PhoneStateListener.LISTEN_SERVICE_STATE
152da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
153da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_CALL_STATE
154da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
155a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_DATA_ACTIVITY
156a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
1570288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk        mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
1580288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                true, mObserver);
1590288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk        mContext.getContentResolver().registerContentObserver(Global.getUriFor(
1600288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                Global.MOBILE_DATA + mSubscriptionInfo.getSubscriptionId()),
1610288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                true, mObserver);
162da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
163da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
164da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
165da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Stop listening for phone state changes.
166da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
167da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void unregisterListener() {
168da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mPhone.listen(mPhoneStateListener, 0);
1690288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk        mContext.getContentResolver().unregisterContentObserver(mObserver);
170da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
171da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
172da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
173da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Produce a mapping of data network types to icon groups for simple and quick use in
174da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * updateTelephony.
175da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
176da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void mapIconSets() {
177da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.clear();
178da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
179da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
180da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
181da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
182da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
183da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
184da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
185da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (!mConfig.showAtLeast3G) {
186da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
187da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.UNKNOWN);
188da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
189da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
190da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
191da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
192da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.G;
193da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
194da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
195da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
196da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
197da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
198da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
199da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
200da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
201da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    TelephonyIcons.THREE_G);
202da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDefaultIcons = TelephonyIcons.THREE_G;
203da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
204da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
205da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
206da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.hspaDataDistinguishable) {
207da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            hGroup = TelephonyIcons.H;
208da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
209da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
210da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
211da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
212da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
213da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
214da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mConfig.show4gForLte) {
215da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
21637d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            if (mConfig.hideLtePlus) {
21737d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
21837d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.FOUR_G);
21937d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            } else {
22037d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
22137d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.FOUR_G_PLUS);
22237d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            }
223da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
224da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
22537d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            if (mConfig.hideLtePlus) {
22637d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
22737d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.LTE);
22837d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            } else {
22937d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
23037d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt                        TelephonyIcons.LTE_PLUS);
23137d34ba893001d59d0c0a70beea87e00b25e22dfRobert Greenwalt            }
232da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
2337150d7fa357e00b2904ff3bcf9e06a1014bfbb39Jason Monk        mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
234da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
235da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
236da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
237e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk    public void notifyListeners(SignalCallback callback) {
238da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        MobileIconGroup icons = getIcons();
239da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
240da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String contentDescription = getStringIfExists(getContentDescription());
241da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
242fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
243fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                && mCurrentState.userSetup;
2445c7daaf7763f4c1fc3eb44430d1b2e5bf11130e1Jeff Davidson
2450f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk        // Show icon in QS when we are connected or data is disabled.
2460f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk        boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
24707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
24807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                getCurrentIconId(), contentDescription);
24907b75fe65dcb5b8add8246654c65f95f1191933eJason Monk
25007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        int qsTypeIcon = 0;
25107b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        IconState qsIcon = null;
25207b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        String description = null;
253da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Only send data sim callbacks to QS.
254da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.dataSim) {
25533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
25607b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            qsIcon = new IconState(mCurrentState.enabled
25707b75fe65dcb5b8add8246654c65f95f1191933eJason Monk                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
25807b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
259da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
26007b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityIn = mCurrentState.dataConnected
2610288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                && !mCurrentState.carrierNetworkChangeMode
2620288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                && mCurrentState.activityIn;
26307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        boolean activityOut = mCurrentState.dataConnected
2640288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                && !mCurrentState.carrierNetworkChangeMode
2650288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                && mCurrentState.activityOut;
2660f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk        showDataIcon &= mCurrentState.isDefault || dataDisabled;
267da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        int typeIcon = showDataIcon ? icons.mDataType : 0;
268e06b065f6e0d0f939b8519ccd3699b90aef818e9Jason Monk        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
2692fdbe128209f02725c645f29bff941efe865da56Andrew Flynn                activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
2700f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
271a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
272a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
273da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
274da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    protected MobileState cleanState() {
275da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return new MobileState();
276da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
277da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
278da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean hasService() {
279da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mServiceState != null) {
280da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // Consider the device to be in service if either voice or data
281da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service is available. Some SIM cards are marketed as data-only
282da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // and do not support voice service, and on these SIM cards, we
283da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // want to show signal bars for data service as well as the "no
284da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // service" or "emergency calls only" text that indicates that voice
285da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // is not available.
286da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            switch (mServiceState.getVoiceRegState()) {
287da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_POWER_OFF:
288da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return false;
289da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_OUT_OF_SERVICE:
290da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                case ServiceState.STATE_EMERGENCY_ONLY:
291da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
292da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                default:
293da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    return true;
294da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
295da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
296da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return false;
297da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
298da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
299da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
300da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isCdma() {
301da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mSignalStrength != null) && !mSignalStrength.isGsm();
302da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
303da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
304da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public boolean isEmergencyOnly() {
305da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        return (mServiceState != null && mServiceState.isEmergencyOnly());
306da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
307da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
308da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private boolean isRoaming() {
309da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isCdma()) {
310da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            final int iconMode = mServiceState.getCdmaEriIconMode();
311da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
312da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
3130288de0e5635b714273ff8185b4bdbfb9ece447cJason Monk                    || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
314da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
315da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return mServiceState != null && mServiceState.getRoaming();
316da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
317da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
318da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
319a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    private boolean isCarrierNetworkChangeActive() {
32055fc8004ad1896da615fd08caca87d1b393d085cAndrew Flynn        return mCurrentState.carrierNetworkChangeMode;
321a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn    }
322a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
323da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void handleBroadcast(Intent intent) {
324da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String action = intent.getAction();
325da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
326da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
327da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
3285504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    intent.getStringExtra(TelephonyIntents.EXTRA_DATA_SPN),
329da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
330da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
331da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            notifyListenersIfNecessary();
332da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
333da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateDataSim();
3348fcab35828144e27a32a95ed9bd83e4f6d83ac21Jason Monk            notifyListenersIfNecessary();
335da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
336da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
337da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
338da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private void updateDataSim() {
339c6cc6266c9325f180b1a073f733fdf0a64e9286fJason Monk        int defaultDataSub = mDefaults.getDefaultDataSubId();
340da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
341da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
342da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
343da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // There doesn't seem to be a data sim selected, however if
344da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // there isn't a MobileSignalController with dataSim set, then
345da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // QS won't get any callbacks and will be blank.  Instead
346da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // lets just assume we are the data sim (which will basically
347da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // show one at random) in QS until one is selected.  The user
348da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // should pick one soon after, so we shouldn't be in this state
349da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            // for long.
350da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.dataSim = true;
351da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
352da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
353da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
354da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
355da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the network's name based on incoming spn and plmn.
356da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
3575504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak    void updateNetworkName(boolean showSpn, String spn, String dataSpn,
3585504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            boolean showPlmn, String plmn) {
359da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (CHATTY) {
3605504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn
3615504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    + " spn=" + spn + " dataSpn=" + dataSpn
362da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
363da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
364da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        StringBuilder str = new StringBuilder();
3655504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        StringBuilder strData = new StringBuilder();
366da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showPlmn && plmn != null) {
367da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(plmn);
3685504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(plmn);
369da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
370da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (showSpn && spn != null) {
371da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (str.length() != 0) {
372da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                str.append(mNetworkNameSeparator);
373da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
374da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            str.append(spn);
375da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
376da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (str.length() != 0) {
377da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = str.toString();
378da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
379da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mNetworkNameDefault;
380da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
3815504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (showSpn && dataSpn != null) {
3825504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            if (strData.length() != 0) {
3835504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                strData.append(mNetworkNameSeparator);
3845504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            }
3855504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            strData.append(dataSpn);
3865504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
3875504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        if (strData.length() != 0) {
3885504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = strData.toString();
3895504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        } else {
3905504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            mCurrentState.networkNameData = mNetworkNameDefault;
3915504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        }
392da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
393da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
394da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    /**
395da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
396da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * mDataState, and mSimState.  It should be called any time one of these is updated.
397da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     * This will call listeners if necessary.
398da68f596282e60bee832dff07cc96bf64bd15939Jason Monk     */
399da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    private final void updateTelephony() {
400da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (DEBUG) {
401da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
402da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    + " ss=" + mSignalStrength);
403da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
404da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.connected = hasService() && mSignalStrength != null;
405da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.connected) {
406da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
407da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getCdmaLevel();
408da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            } else {
409da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                mCurrentState.level = mSignalStrength.getLevel();
410da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
411da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
412da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
413da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
414da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        } else {
415da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.iconGroup = mDefaultIcons;
416da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
417da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.dataConnected = mCurrentState.connected
418da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                && mDataState == TelephonyManager.DATA_CONNECTED;
419da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
4200f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk        mCurrentState.roaming = isRoaming();
421a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        if (isCarrierNetworkChangeActive()) {
422a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
4231a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk        } else if (isDataDisabled()) {
4241a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
425da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
426da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (isEmergencyOnly() != mCurrentState.isEmergency) {
427da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.isEmergency = isEmergencyOnly();
428da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mNetworkController.recalculateEmergency();
429da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
430da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        // Fill in the network name if we think we have it.
431da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
43293fb68fdce8f0d28eaa77704e4b00933260b83ddJason Monk                && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
433da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
434da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
435a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
436da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
437da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
438da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
4391a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk    private boolean isDataDisabled() {
4401a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk        return !mPhone.getDataEnabled(mSubscriptionInfo.getSubscriptionId());
4411a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk    }
4421a95c86281bc9c2c187b3f4df19d2805595b6f26Jason Monk
443da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @VisibleForTesting
444da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    void setActivity(int activity) {
445da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
446da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_IN;
447da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
448da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                || activity == TelephonyManager.DATA_ACTIVITY_OUT;
449da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        notifyListenersIfNecessary();
450da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
451da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
452da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    @Override
453da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    public void dump(PrintWriter pw) {
454da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        super.dump(pw);
455da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSubscription=" + mSubscriptionInfo + ",");
456da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mServiceState=" + mServiceState + ",");
457da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mSignalStrength=" + mSignalStrength + ",");
458da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataState=" + mDataState + ",");
459da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        pw.println("  mDataNetType=" + mDataNetType + ",");
460da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
461da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
462da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    class MobilePhoneStateListener extends PhoneStateListener {
46307b75fe65dcb5b8add8246654c65f95f1191933eJason Monk        public MobilePhoneStateListener(int subId, Looper looper) {
46407b75fe65dcb5b8add8246654c65f95f1191933eJason Monk            super(subId, looper);
465da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
466da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
467da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
468da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
469da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
470da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
471da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
472da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
473da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mSignalStrength = signalStrength;
474da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
475da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
476da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
477da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
478da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onServiceStateChanged(ServiceState state) {
479da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
480da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
481da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " dataState=" + state.getDataRegState());
482da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
483da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mServiceState = state;
48467b2c16a9a9060d37888bdab4dfadd384a76e9d7Jason Monk            mDataNetType = state.getDataNetworkType();
485ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
486ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt                    mServiceState.isUsingCarrierAggregation()) {
487ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt                mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
488ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt            }
489da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
490da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
491da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
492da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
493da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataConnectionStateChanged(int state, int networkType) {
494da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
495da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataConnectionStateChanged: state=" + state
496da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                        + " type=" + networkType);
497da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
498da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataState = state;
499da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataNetType = networkType;
500ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE && mServiceState != null &&
501ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt                    mServiceState.isUsingCarrierAggregation()) {
502ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt                mDataNetType = TelephonyManager.NETWORK_TYPE_LTE_CA;
503ea0d71390ab528ffea7161674333b0bbab8356dfRobert Greenwalt            }
504da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            updateTelephony();
505da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
506da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
507da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
508da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void onDataActivity(int direction) {
509da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            if (DEBUG) {
510da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                Log.d(mTag, "onDataActivity: direction=" + direction);
511da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            }
512da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            setActivity(direction);
513da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
514a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
515a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        @Override
516a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        public void onCarrierNetworkChange(boolean active) {
517a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            if (DEBUG) {
518a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                Log.d(mTag, "onCarrierNetworkChange: active=" + active);
519a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            }
520a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            mCurrentState.carrierNetworkChangeMode = active;
521a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn
522a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            updateTelephony();
523a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        }
524da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    };
525da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
526da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileIconGroup extends SignalController.IconGroup {
527da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataContentDescription; // mContentDescriptionDataType
528da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final int mDataType;
529da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        final boolean mIsWide;
53033f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        final int mQsDataType;
531da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
532da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
533da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
534da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
53533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk                int qsDataType) {
5362fdbe128209f02725c645f29bff941efe865da56Andrew Flynn            super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
5372fdbe128209f02725c645f29bff941efe865da56Andrew Flynn                    qsDiscState, discContentDesc);
538da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataContentDescription = dataContentDesc;
539da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mDataType = dataType;
540da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mIsWide = isWide;
541da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            mQsDataType = qsDataType;
542da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
543da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
544da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
545da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    static class MobileState extends SignalController.State {
546da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        String networkName;
5475504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak        String networkNameData;
548da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataSim;
549da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean dataConnected;
550da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean isEmergency;
551da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        boolean airplaneMode;
552a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn        boolean carrierNetworkChangeMode;
55333f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk        boolean isDefault;
554fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk        boolean userSetup;
5550f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk        boolean roaming;
556da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
557da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
558da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public void copyFrom(State s) {
559da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.copyFrom(s);
560da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            MobileState state = (MobileState) s;
561da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataSim = state.dataSim;
562da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            networkName = state.networkName;
5635504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            networkNameData = state.networkNameData;
564da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            dataConnected = state.dataConnected;
56533f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            isDefault = state.isDefault;
566da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            isEmergency = state.isEmergency;
567da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            airplaneMode = state.airplaneMode;
568a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
569fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            userSetup = state.userSetup;
5700f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk            roaming = state.roaming;
571da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
572da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
573da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
574da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        protected void toString(StringBuilder builder) {
575da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            super.toString(builder);
576da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append(',');
577da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataSim=").append(dataSim).append(',');
578da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("networkName=").append(networkName).append(',');
5795504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak            builder.append("networkNameData=").append(networkNameData).append(',');
580da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("dataConnected=").append(dataConnected).append(',');
5810f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk            builder.append("roaming=").append(roaming).append(',');
58233f8ae7543fbf7d94266f0f1621ec873aa2542f1Jason Monk            builder.append("isDefault=").append(isDefault).append(',');
583da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            builder.append("isEmergency=").append(isEmergency).append(',');
584a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn            builder.append("airplaneMode=").append(airplaneMode).append(',');
585fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
586fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                    .append(',');
587fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk            builder.append("userSetup=").append(userSetup);
588da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
589da68f596282e60bee832dff07cc96bf64bd15939Jason Monk
590da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        @Override
591da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        public boolean equals(Object o) {
592da68f596282e60bee832dff07cc96bf64bd15939Jason Monk            return super.equals(o)
593da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && Objects.equals(((MobileState) o).networkName, networkName)
5945504d39b7f880fa8b8660e5d4b014ec559124cf9Pavel Zhamaitsiak                    && Objects.equals(((MobileState) o).networkNameData, networkNameData)
595da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataSim == dataSim
596da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).dataConnected == dataConnected
597da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).isEmergency == isEmergency
598da68f596282e60bee832dff07cc96bf64bd15939Jason Monk                    && ((MobileState) o).airplaneMode == airplaneMode
599a478d70a68696380acbd4a9739dfaaebff61c728Andrew Flynn                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
600fd57ea730e65afd6dcb848664dde0cdb64624659Jason Monk                    && ((MobileState) o).userSetup == userSetup
6010f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk                    && ((MobileState) o).isDefault == isDefault
6020f0de13c37082f9443e3f0c8cc413188ec66d3feJason Monk                    && ((MobileState) o).roaming == roaming;
603da68f596282e60bee832dff07cc96bf64bd15939Jason Monk        }
604da68f596282e60bee832dff07cc96bf64bd15939Jason Monk    }
605da68f596282e60bee832dff07cc96bf64bd15939Jason Monk}
606