MSIM support for Statusbar.

-Add support for Signal Strength icon display for MultiSim

Display dual subscription info in notification panel
  -Show subscription information for both subscriptions
   relevant to the sim state. if sim state is ready show
   operator name, if card absent, show no sim message,
   if UE is in airplane mode, show airplane mode message.

Clear data activity icon when disconnected
  -If data is disconnected before data activity becomes none,
   then clear up/down arrow icon by reset the data activity icon.

Add support for ro.config.combined_signal
  -Add support for ro.config.combined_signal. This property is being used
   to consider data service state for signal display.
   When ro.config.combined_signal is not set to false, we will display
   CS/PS signal strength whichever is available

Conflicts:
packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
Change-Id: Iebc9f49334a8a3cf469ea2624f0e1d6eb50b63bc
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5644a0e..9bbfd06 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2575,6 +2575,8 @@
 
     <!-- Shown in the lock screen when there is emergency calls only mode. -->
     <string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
+    <!-- Shown in the lock screen when there is SIM card IO error. -->
+    <string name="lockscreen_sim_error_message_short">Invalid Card.</string>
 
     <!-- When the user inserts a sim card from an unsupported network, it becomes network
          locked -->
@@ -2595,6 +2597,9 @@
          progress dialog in the meantime.  this is the emssage. -->
     <string name="lockscreen_sim_unlock_progress_dialog_message">Unlocking SIM card\u2026</string>
 
+    <!-- Shown in the lock screen to tell the user that phone is in airplane mode-->
+    <string name="lockscreen_airplane_mode_on">Airplane Mode</string>
+
     <!-- For the unlock screen, Information message shown in dialog when user has too many failed attempts at
          drawing the unlock pattern -->
     <string name="lockscreen_too_many_failed_attempts_dialog_message">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a62c1ec..ffbc349 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -516,6 +516,7 @@
   <java-symbol type="string" name="autofill_zip_code_re" />
   <java-symbol type="string" name="badPin" />
   <java-symbol type="string" name="badPuk" />
+  <java-symbol type="string" name="lockscreen_sim_error_message_short" />
   <java-symbol type="string" name="byteShort" />
   <java-symbol type="string" name="capability_desc_canRequestEnhancedWebAccessibility" />
   <java-symbol type="string" name="capability_title_canRequestFilterKeyEvents" />
@@ -1518,7 +1519,12 @@
   <java-symbol type="string" name="global_action_toggle_silent_mode" />
   <java-symbol type="string" name="global_action_lockdown" />
   <java-symbol type="string" name="invalidPuk" />
+  <java-symbol type="string" name="lockscreen_missing_sim_message_short" />
+  <java-symbol type="string" name="lockscreen_permanent_disabled_sim_message_short" />
   <java-symbol type="string" name="lockscreen_carrier_default" />
+  <java-symbol type="string" name="lockscreen_sim_locked_message" />
+  <java-symbol type="string" name="lockscreen_sim_puk_locked_message" />
+  <java-symbol type="string" name="lockscreen_airplane_mode_on" />
   <java-symbol type="style" name="Animation.LockScreen" />
   <java-symbol type="style" name="Theme.Dialog.RecentApplications" />
   <java-symbol type="style" name="Theme.ExpandedMenu" />
diff --git a/packages/SystemUI/res/layout/msim_keyguard_status_bar.xml b/packages/SystemUI/res/layout/msim_keyguard_status_bar.xml
new file mode 100644
index 0000000..f3a1331
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_keyguard_status_bar.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!-- Extends RelativeLayout -->
+<com.android.systemui.statusbar.phone.KeyguardStatusBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/keyguard_header"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/status_bar_header_height_keyguard"
+    android:baselineAligned="false"
+    >
+
+    <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
+        android:layout_width="@dimen/multi_user_switch_width_keyguard"
+        android:layout_height="@dimen/status_bar_header_height_keyguard"
+        android:layout_alignParentEnd="true"
+        android:background="@drawable/ripple_drawable"
+        android:layout_marginEnd="@dimen/multi_user_switch_keyguard_margin">
+        <ImageView android:id="@+id/multi_user_avatar"
+            android:layout_width="@dimen/multi_user_avatar_keyguard_size"
+            android:layout_height="@dimen/multi_user_avatar_keyguard_size"
+            android:layout_gravity="center"
+            android:scaleType="centerInside"/>
+    </com.android.systemui.statusbar.phone.MultiUserSwitch>
+
+    <LinearLayout android:id="@+id/system_icons_super_container"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/status_bar_header_height"
+        android:layout_toStartOf="@id/multi_user_switch"
+        android:layout_alignWithParentIfMissing="true"
+        android:layout_marginStart="16dp"
+        android:paddingEnd="2dp">
+        <FrameLayout android:id="@+id/system_icons_container"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/status_bar_height"
+            android:layout_gravity="center_vertical"
+            >
+            <include layout="@layout/msim_system_icons" />
+        </FrameLayout>
+        <TextView android:id="@+id/battery_level"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_marginStart="@dimen/header_battery_margin_keyguard"
+            android:paddingEnd="@dimen/battery_level_padding_end"
+            android:textColor="#ffffff"
+            android:visibility="gone"
+            android:textSize="12sp"/>
+    </LinearLayout>
+
+    <com.android.keyguard.CarrierText
+        android:id="@+id/keyguard_carrier_text"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/status_bar_header_height_keyguard"
+        android:layout_marginStart="@dimen/keyguard_carrier_text_margin"
+        android:layout_toStartOf="@id/system_icons_super_container"
+        android:gravity="center_vertical"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textColor="#ffffff"
+        android:singleLine="true" />
+
+</com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/msim_signal_cluster_view.xml b/packages/SystemUI/res/layout/msim_signal_cluster_view.xml
new file mode 100644
index 0000000..a6b2c2d
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_signal_cluster_view.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** Copyright 2011 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.statusbar.MSimSignalClusterView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="wrap_content"
+    android:gravity="center_vertical"
+    android:orientation="horizontal"
+    >
+    <FrameLayout
+        android:id="@+id/wifi_combo"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        >
+        <ImageView
+            android:id="@+id/wifi_signal"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            />
+    </FrameLayout>
+    <View
+        android:layout_height="6dp"
+        android:layout_width="6dp"
+        android:visibility="gone"
+        android:id="@+id/spacer"
+        />
+    <!--<FrameLayout
+        android:id="@+id/wimax_combo"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginRight="-6dp"
+        >
+        <ImageView
+            android:id="@+id/wimax_signal"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:scaleType="center"
+            />
+        <ImageView
+            android:id="@+id/wimax_inout"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_gravity="center|bottom"
+            />
+    </FrameLayout>
+    -->
+    <FrameLayout
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        >
+        <View
+            android:layout_height="6dp"
+            android:layout_width="6dp"
+            android:visibility="invisible"
+            />
+        <FrameLayout
+            android:id="@+id/mobile_combo_sub3"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            >
+            <ImageView
+                android:id="@+id/mobile_signal_sub3"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_type_sub3"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_inout_sub3"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="right|bottom"
+                />
+            <ImageView
+                android:id="@+id/no_sim_slot3"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                />
+        </FrameLayout>
+    </FrameLayout>
+    <View
+        android:layout_height="8dp"
+        android:layout_width="8dp"
+        android:id="@+id/spacer"
+        />
+    <FrameLayout
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        >
+        <View
+            android:layout_height="6dp"
+            android:layout_width="6dp"
+            android:visibility="invisible"
+            />
+        <FrameLayout
+            android:id="@+id/mobile_combo_sub2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            >
+            <ImageView
+                android:id="@+id/mobile_signal_sub2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_type_sub2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_inout_sub2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="right|bottom"
+                />
+            <ImageView
+                android:id="@+id/no_sim_slot2"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                />
+        </FrameLayout>
+    </FrameLayout>
+    <View
+        android:layout_height="8dp"
+        android:layout_width="8dp"
+        android:id="@+id/spacer"
+        />
+    <FrameLayout
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        >
+        <View
+            android:layout_height="6dp"
+            android:layout_width="6dp"
+            android:visibility="invisible"
+            />
+        <FrameLayout
+            android:id="@+id/mobile_combo"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            >
+            <ImageView
+                android:id="@+id/mobile_signal"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_type"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="center|bottom"
+                />
+            <ImageView
+                android:id="@+id/mobile_inout"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:layout_gravity="right|bottom"
+                />
+            <ImageView
+                android:id="@+id/no_sim"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                />
+        </FrameLayout>
+    </FrameLayout>
+    <ImageView
+        android:id="@+id/airplane"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        />
+</com.android.systemui.statusbar.MSimSignalClusterView>
diff --git a/packages/SystemUI/res/layout/msim_status_bar.xml b/packages/SystemUI/res/layout/msim_status_bar.xml
new file mode 100644
index 0000000..6022ec6
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_status_bar.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<!--    android:background="@drawable/status_bar_closed_default_background" -->
+<com.android.systemui.statusbar.phone.PhoneStatusBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/msim_status_bar"
+    android:background="@drawable/system_bar_background"
+    android:orientation="vertical"
+    android:focusable="true"
+    android:descendantFocusability="afterDescendants"
+    >
+
+    <ImageView
+        android:id="@+id/notification_lights_out"
+        android:layout_width="@dimen/status_bar_icon_size"
+        android:layout_height="match_parent"
+        android:paddingStart="6dip"
+        android:paddingBottom="2dip"
+        android:src="@drawable/ic_sysbar_lights_out_dot_small"
+        android:scaleType="center"
+        android:visibility="gone"
+        />
+
+    <LinearLayout android:id="@+id/status_bar_contents"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingStart="6dip"
+        android:paddingEnd="6dip"
+        android:orientation="horizontal"
+        >
+
+        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+            android:id="@+id/notification_icon_area"
+            android:layout_width="0dip"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:orientation="horizontal"
+            >
+            <!-- The alpha of this area is both controlled from PhoneStatusBarTransitions and
+                 PhoneStatusBar (DISABLE_NOTIFICATION_ICONS), so we need two views here. -->
+            <com.android.systemui.statusbar.AlphaOptimizedLinearLayout
+                android:id="@+id/notification_icon_area_inner"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                >
+                <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/moreIcon"
+                    android:layout_width="@dimen/status_bar_icon_size"
+                    android:layout_height="match_parent"
+                    android:src="@drawable/stat_notify_more"
+                    android:visibility="gone"
+                    />
+                <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_alignParentStart="true"
+                    android:gravity="center_vertical"
+                    android:orientation="horizontal"/>
+            </com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
+        </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+        <com.android.systemui.statusbar.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:orientation="horizontal"
+            >
+
+            <include layout="@layout/msim_system_icons" />
+
+            <com.android.systemui.statusbar.policy.Clock
+                android:id="@+id/clock"
+                android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:singleLine="true"
+                android:paddingStart="6dip"
+                android:gravity="center_vertical|start"
+                />
+        </com.android.systemui.statusbar.AlphaOptimizedLinearLayout>
+    </LinearLayout>
+
+    <ViewStub
+        android:id="@+id/ticker_stub"
+        android:inflatedId="@+id/ticker"
+        android:layout="@layout/status_bar_ticker"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+
+</com.android.systemui.statusbar.phone.PhoneStatusBarView>
diff --git a/packages/SystemUI/res/layout/msim_status_bar_expanded.xml b/packages/SystemUI/res/layout/msim_status_bar_expanded.xml
new file mode 100644
index 0000000..b7e9a8b
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_status_bar_expanded.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright (c) 2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.statusbar.phone.NotificationPanelView 
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/notification_panel"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/transparent"
+    >
+
+   <include
+            layout="@layout/subs_label"
+            android:layout_height="@dimen/carrier_label_height"
+            android:layout_width="match_parent"
+            android:layout_gravity="bottom"
+            />
+    <include
+        layout="@layout/carrier_label"
+        android:layout_height="@dimen/carrier_label_height"
+        android:layout_width="match_parent"
+        android:layout_marginBottom="@dimen/close_handle_height"
+        android:layout_gravity="bottom"
+        />
+
+    <include
+        layout="@layout/keyguard_status_view"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/emergency_calls_only"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:padding="4dp"
+        android:gravity="center"
+        android:visibility="gone"
+        />
+
+    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="@integer/notification_panel_layout_gravity"
+        android:id="@+id/notification_container_parent"
+        android:clipToPadding="false"
+        android:clipChildren="false">
+
+        <com.android.systemui.statusbar.phone.ObservableScrollView
+            android:id="@+id/scroll_view"
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="match_parent"
+            android:layout_gravity="@integer/notification_panel_layout_gravity"
+            android:scrollbars="none"
+            android:overScrollMode="never"
+            android:fillViewport="true">
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+                <include
+                    layout="@layout/qs_panel"
+                    android:layout_marginTop="@dimen/status_bar_header_height_expanded"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/notification_side_padding"
+                    android:layout_marginRight="@dimen/notification_side_padding"/>
+
+                <!-- A view to reserve space for the collapsed stack -->
+                <!-- Layout height: notification_min_height + bottom_stack_peek_amount -->
+                <View
+                    android:id="@+id/reserve_notification_space"
+                    android:layout_height="@dimen/min_stack_height"
+                    android:layout_width="match_parent"
+                    android:layout_marginTop="@dimen/notifications_top_padding" />
+
+                <View
+                    android:layout_height="@dimen/notification_side_padding"
+                    android:layout_width="match_parent" />
+            </LinearLayout>
+        </com.android.systemui.statusbar.phone.ObservableScrollView>
+
+        <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+            android:id="@+id/notification_stack_scroller"
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="match_parent"
+            android:layout_gravity="@integer/notification_panel_layout_gravity"
+            android:layout_marginBottom="@dimen/close_handle_underlap"/>
+
+        <ViewStub
+            android:id="@+id/keyguard_user_switcher"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_marginTop="@dimen/status_bar_header_height_keyguard"
+            android:layout_gravity="end"
+            android:layout="@layout/keyguard_user_switcher" />
+
+        <include
+            layout="@layout/msim_keyguard_status_bar"
+            android:visibility="invisible" />
+
+    </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
+
+    <include layout="@layout/status_bar_expanded_header" />
+
+    <include
+        layout="@layout/keyguard_bottom_area"
+        android:visibility="gone" />
+
+    <com.android.systemui.statusbar.AlphaOptimizedView
+        android:id="@+id/qs_navbar_scrim"
+        android:layout_height="96dp"
+        android:layout_width="match_parent"
+        android:layout_gravity="bottom"
+        android:visibility="invisible"
+        android:background="@drawable/qs_navbar_scrim" />
+
+</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/msim_super_status_bar.xml b/packages/SystemUI/res/layout/msim_super_status_bar.xml
new file mode 100644
index 0000000..c3ec2f3
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_super_status_bar.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+** Not a Contribution.
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the combined status bar / notification panel window. -->
+<com.android.systemui.statusbar.phone.StatusBarWindowView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:focusable="true"
+    android:fitsSystemWindows="true"
+    android:descendantFocusability="afterDescendants">
+
+    <FrameLayout android:id="@+id/brightness_mirror"
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="@integer/notification_panel_layout_gravity"
+            android:paddingLeft="@dimen/notification_side_padding"
+            android:paddingRight="@dimen/notification_side_padding"
+            android:visibility="gone">
+        <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:elevation="2dp"
+                android:background="@drawable/brightness_mirror_background">
+            <include layout="@layout/quick_settings_brightness_dialog" />
+        </FrameLayout>
+    </FrameLayout>
+
+    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+            android:id="@+id/backdrop"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="gone"
+            >
+        <ImageView android:id="@+id/backdrop_back"
+                   android:layout_width="match_parent"
+                   android:scaleType="centerCrop"
+                   android:layout_height="match_parent" />
+        <ImageView android:id="@+id/backdrop_front"
+                   android:layout_width="match_parent"
+                   android:layout_height="match_parent"
+                   android:scaleType="centerCrop"
+                   android:visibility="invisible" />
+    </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
+
+    <View android:id="@+id/scrim_behind"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <include layout="@layout/msim_status_bar"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/status_bar_height" />
+
+    <com.android.systemui.statusbar.phone.PanelHolder
+        android:id="@+id/msim_panel_holder"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/transparent" >
+        <include layout="@layout/msim_status_bar_expanded"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="gone" />
+    </com.android.systemui.statusbar.phone.PanelHolder>
+
+    <View android:id="@+id/scrim_in_front"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/msim_system_icons.xml b/packages/SystemUI/res/layout/msim_system_icons.xml
new file mode 100644
index 0000000..8834a24
--- /dev/null
+++ b/packages/SystemUI/res/layout/msim_system_icons.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/system_icons"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:gravity="center_vertical">
+
+    <com.android.systemui.statusbar.AlphaOptimizedLinearLayout android:id="@+id/statusIcons"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"/>
+
+    <include layout="@layout/msim_signal_cluster_view"
+        android:id="@+id/msim_signal_cluster"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="2dp"/>
+
+    <!-- battery must be padded below to match assets -->
+    <com.android.systemui.BatteryMeterView android:id="@+id/battery"
+        android:layout_height="16dp"
+        android:layout_width="10.5dp"
+        android:layout_marginBottom="0.33dp"
+        android:layout_marginStart="4dip"/>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/subs_label.xml b/packages/SystemUI/res/layout/subs_label.xml
new file mode 100644
index 0000000..51c46a3
--- /dev/null
+++ b/packages/SystemUI/res/layout/subs_label.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+-->
+
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/subs_label"
+    android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network"
+    android:layout_height="@dimen/carrier_label_height"
+    android:layout_width="match_parent"
+    android:layout_marginBottom="@dimen/close_handle_height"
+    android:layout_gravity="bottom"
+    android:gravity="center"
+    android:visibility="invisible"
+    />
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MSimSignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/MSimSignalClusterView.java
new file mode 100644
index 0000000..859c729
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MSimSignalClusterView.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.os.Build;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.MSimNetworkControllerImpl;
+
+import com.android.systemui.R;
+
+
+// Intimately tied to the design of res/layout/msim_signal_cluster_view.xml
+public class MSimSignalClusterView
+        extends LinearLayout
+        implements MSimNetworkControllerImpl.MSimSignalCluster {
+
+    static final boolean DEBUG = true;
+    static final String TAG = "MSimSignalClusterView";
+
+
+    MSimNetworkControllerImpl mMSimNC;
+
+    private boolean mWifiVisible = false;
+    private int mWifiStrengthId = 0;
+    private boolean mMobileVisible = false;
+    private int[] mMobileStrengthId;
+    private int[] mMobileActivityId;
+    private int[] mMobileTypeId;
+    private int[] mNoSimIconId;
+    private boolean mIsAirplaneMode = false;
+    private int mAirplaneIconId = 0;
+    private String mWifiDescription, mMobileTypeDescription;
+    private String[] mMobileDescription;
+
+    ViewGroup mWifiGroup;
+    ViewGroup[] mMobileGroup;
+    ImageView mWifi, mAirplane;
+    ImageView[] mNoSimSlot;
+    ImageView[] mMobile;
+    ImageView[] mMobileActivity;
+    ImageView[] mMobileType;
+    View mSpacer;
+    private int[] mMobileGroupResourceId = {R.id.mobile_combo, R.id.mobile_combo_sub2,
+                                          R.id.mobile_combo_sub3};
+    private int[] mMobileResourceId = {R.id.mobile_signal, R.id.mobile_signal_sub2,
+                                     R.id.mobile_signal_sub3};
+    private int[] mMobileActResourceId = {R.id.mobile_inout, R.id.mobile_inout_sub2,
+                                        R.id.mobile_inout_sub3};
+    private int[] mMobileTypeResourceId = {R.id.mobile_type, R.id.mobile_type_sub2,
+                                         R.id.mobile_type_sub3};
+    private int[] mNoSimSlotResourceId = {R.id.no_sim, R.id.no_sim_slot2, R.id.no_sim_slot3};
+    private int mNumPhones = TelephonyManager.getDefault().getPhoneCount();
+
+    public MSimSignalClusterView(Context context) {
+        this(context, null);
+    }
+
+    public MSimSignalClusterView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public MSimSignalClusterView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mMobileStrengthId = new int[mNumPhones];
+        mMobileDescription = new String[mNumPhones];
+        mMobileTypeId = new int[mNumPhones];
+        mMobileActivityId = new int[mNumPhones];
+        mNoSimIconId = new int[mNumPhones];
+        mMobileGroup = new ViewGroup[mNumPhones];
+        mNoSimSlot = new ImageView[mNumPhones];
+        mMobile = new ImageView[mNumPhones];
+        mMobileActivity = new ImageView[mNumPhones];
+        mMobileType = new ImageView[mNumPhones];
+        for (int i=0; i < mNumPhones; i++) {
+            mMobileStrengthId[i] = 0;
+            mMobileTypeId[i] = 0;
+            mMobileActivityId[i] = 0;
+            mNoSimIconId[i] = 0;
+        }
+    }
+
+    public void setNetworkController(MSimNetworkControllerImpl nc) {
+        if (DEBUG) Slog.d(TAG, "MSimNetworkController=" + nc);
+        mMSimNC = nc;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+
+        mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
+        mWifi           = (ImageView) findViewById(R.id.wifi_signal);
+        mSpacer         =             findViewById(R.id.spacer);
+        mAirplane       = (ImageView) findViewById(R.id.airplane);
+
+        for (int i = 0; i < mNumPhones; i++) {
+            mMobileGroup[i]    = (ViewGroup) findViewById(mMobileGroupResourceId[i]);
+            mMobile[i]         = (ImageView) findViewById(mMobileResourceId[i]);
+            mMobileActivity[i] = (ImageView) findViewById(mMobileActResourceId[i]);
+            mMobileType[i]     = (ImageView) findViewById(mMobileTypeResourceId[i]);
+            mNoSimSlot[i]      = (ImageView) findViewById(mNoSimSlotResourceId[i]);
+        }
+        apply(SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubId()));
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mWifiGroup      = null;
+        mWifi           = null;
+        mSpacer         = null;
+        mAirplane       = null;
+        for (int i = 0; i < mNumPhones; i++) {
+            mMobileGroup[i]    = null;
+            mMobile[i]         = null;
+            mMobileActivity[i] = null;
+            mMobileType[i]     = null;
+            mNoSimSlot[i]      = null;
+        }
+        super.onDetachedFromWindow();
+    }
+
+    @Override
+    public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
+        mWifiVisible = visible;
+        mWifiStrengthId = strengthIcon;
+        mWifiDescription = contentDescription;
+        apply(SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubId()));
+    }
+
+    @Override
+    public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
+            String contentDescription, String typeContentDescription,
+            int phoneId) {
+        mMobileVisible = visible;
+        mMobileStrengthId[phoneId] = strengthIcon;
+        mMobileTypeId[phoneId] = typeIcon;
+        mMobileDescription[phoneId] = contentDescription;
+        mMobileTypeDescription = typeContentDescription;
+
+        apply(phoneId);
+    }
+
+    @Override
+    public void setIsAirplaneMode(boolean is, int airplaneIconId) {
+        mIsAirplaneMode = is;
+        mAirplaneIconId = airplaneIconId;
+        for (int i = 0; i < mNumPhones; i++) {
+            apply(i);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+        // Standard group layout onPopulateAccessibilityEvent() implementations
+        // ignore content description, so populate manually
+        if (mWifiVisible && mWifiGroup != null &&
+                mWifiGroup.getContentDescription() != null)
+            event.getText().add(mWifiGroup.getContentDescription());
+        if (mMobileVisible && mMobileGroup[PhoneConstants.DEFAULT_SUBSCRIPTION] != null
+                && mMobileGroup[PhoneConstants.DEFAULT_SUBSCRIPTION].
+                getContentDescription() != null)
+            event.getText().add(mMobileGroup[PhoneConstants.DEFAULT_SUBSCRIPTION].
+                    getContentDescription());
+        return super.dispatchPopulateAccessibilityEvent(event);
+    }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
+
+
+    // Run after each indicator change.
+    private void apply(int phoneId) {
+        if (mWifiGroup == null) return;
+
+        if (mWifiVisible) {
+            mWifiGroup.setVisibility(View.VISIBLE);
+            mWifi.setImageResource(mWifiStrengthId);
+            mWifiGroup.setContentDescription(mWifiDescription);
+        } else {
+            mWifiGroup.setVisibility(View.GONE);
+        }
+
+        if (DEBUG) Slog.d(TAG,
+                String.format("wifi: %s sig=%d ",
+                (mWifiVisible ? "VISIBLE" : "GONE"), mWifiStrengthId));
+
+        if (mMobileVisible && !mIsAirplaneMode) {
+            mMobileGroup[phoneId].setVisibility(View.VISIBLE);
+            mMobile[phoneId].setImageResource(mMobileStrengthId[phoneId]);
+            mMobileGroup[phoneId].setContentDescription(mMobileTypeDescription + " "
+                + mMobileDescription[phoneId]);
+            mMobileActivity[phoneId].setImageResource(mMobileActivityId[phoneId]);
+            mMobileType[phoneId].setImageResource(mMobileTypeId[phoneId]);
+            mMobileType[phoneId].setVisibility(
+                !mWifiVisible ? View.VISIBLE : View.GONE);
+            mNoSimSlot[phoneId].setImageResource(mNoSimIconId[phoneId]);
+        } else {
+            mMobileGroup[phoneId].setVisibility(View.GONE);
+        }
+
+        if (mIsAirplaneMode) {
+            mAirplane.setVisibility(View.VISIBLE);
+            mAirplane.setImageResource(mAirplaneIconId);
+        } else {
+            mAirplane.setVisibility(View.GONE);
+        }
+
+        if (phoneId != 0) {
+            if (mMobileVisible && mWifiVisible && ((mIsAirplaneMode) ||
+                    (mNoSimIconId[phoneId] != 0))) {
+                mSpacer.setVisibility(View.INVISIBLE);
+            } else {
+                mSpacer.setVisibility(View.GONE);
+            }
+        }
+
+    }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 9e3f0f6..feb6f9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -77,6 +77,7 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -132,6 +133,7 @@
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.MSimSignalClusterView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
 import com.android.systemui.statusbar.NotificationOverflowContainer;
@@ -153,6 +155,7 @@
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.MSimNetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
@@ -248,6 +251,7 @@
     KeyguardMonitor mKeyguardMonitor;
     BrightnessMirrorController mBrightnessMirrorController;
     AccessibilityController mAccessibilityController;
+    MSimNetworkControllerImpl mMSimNetworkController;
 
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
@@ -312,6 +316,7 @@
 
     // carrier/wifi label
     private TextView mCarrierLabel;
+    private TextView mSubsLabel;
     private boolean mCarrierLabelVisible = false;
     private int mCarrierLabelHeight;
     private int mStatusBarHeaderHeight;
@@ -605,6 +610,10 @@
         notifyUserAboutHiddenNotifications();
     }
 
+    boolean isMSim() {
+        return (TelephonyManager.getDefault().getPhoneCount() > 1);
+    }
+
     // ================================================================================
     // Constructing the view
     // ================================================================================
@@ -618,8 +627,13 @@
 
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
 
-        mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
-                R.layout.super_status_bar, null);
+        if (isMSim()) {
+            mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
+                    R.layout.msim_super_status_bar, null);
+        } else {
+            mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
+                    R.layout.super_status_bar, null);
+        }
         mStatusBarWindow.mService = this;
         mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
             @Override
@@ -633,10 +647,20 @@
                 return mStatusBarWindow.onTouchEvent(event);
             }});
 
-        mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
+        if (isMSim()) {
+            mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(
+                    R.id.msim_status_bar);
+        } else {
+            mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
+        }
         mStatusBarView.setBar(this);
 
-        PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+        PanelHolder holder;
+        if (isMSim()) {
+            holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.msim_panel_holder);
+        } else {
+            holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+        }
         mStatusBarView.setPanelHolder(holder);
 
         mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
@@ -789,7 +813,6 @@
                 // noop
             }
         });
-        mNetworkController = new NetworkControllerImpl(mContext);
         mHotspotController = new HotspotControllerImpl(mContext);
         mBluetoothController = new BluetoothControllerImpl(mContext);
         mSecurityController = new SecurityControllerImpl(mContext);
@@ -800,38 +823,79 @@
         mVolumeComponent = getComponent(VolumeComponent.class);
         mZenModeController = mVolumeComponent.getZenController();
         mCastController = new CastControllerImpl(mContext);
-        final SignalClusterView signalCluster =
-                (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
-        final SignalClusterView signalClusterKeyguard =
+
+        if (isMSim()) {
+            mMSimNetworkController = new MSimNetworkControllerImpl(mContext);
+            MSimSignalClusterView mSimSignalCluster = (MSimSignalClusterView)
+              mStatusBarView.findViewById(R.id.msim_signal_cluster);
+            for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+                mMSimNetworkController.addSignalCluster(mSimSignalCluster, i);
+            }
+            mSimSignalCluster.setNetworkController(mMSimNetworkController);
+
+            mMSimNetworkController.addEmergencyLabelView(mHeader);
+
+            mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+            mSubsLabel = (TextView)mStatusBarWindow.findViewById(R.id.subs_label);
+            mShowCarrierInPanel = (mCarrierLabel != null);
+
+            if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" +
+                                    mShowCarrierInPanel + "operator label=" + mSubsLabel);
+            if (mShowCarrierInPanel) {
+                mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
+
+                // for mobile devices, we always show mobile connection info here (SPN/PLMN)
+                // for other devices, we show whatever network is connected
+                if (mMSimNetworkController.hasMobileDataFeature()) {
+                    mMSimNetworkController.addMobileLabelView(mCarrierLabel);
+                } else {
+                    mMSimNetworkController.addCombinedLabelView(mCarrierLabel);
+                }
+                mSubsLabel.setVisibility(View.VISIBLE);
+                mMSimNetworkController.addSubsLabelView(mSubsLabel);
+                // set up the dynamic hide/show of the label
+                //mPile.setOnSizeChangedListener(new OnSizeChangedListener() {
+                //    @Override
+                //    public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
+                //        updateCarrierLabelVisibility(false);
+                //    }
+                //});
+            }
+        } else {
+            mNetworkController = new NetworkControllerImpl(mContext);
+            final SignalClusterView signalCluster =
+                (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
+            final SignalClusterView signalClusterKeyguard =
                 (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
-        final SignalClusterView signalClusterQs =
+            final SignalClusterView signalClusterQs =
                 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
-        mNetworkController.addSignalCluster(signalCluster);
-        mNetworkController.addSignalCluster(signalClusterKeyguard);
-        mNetworkController.addSignalCluster(signalClusterQs);
-        signalCluster.setSecurityController(mSecurityController);
-        signalCluster.setNetworkController(mNetworkController);
-        signalClusterKeyguard.setSecurityController(mSecurityController);
-        signalClusterKeyguard.setNetworkController(mNetworkController);
-        signalClusterQs.setSecurityController(mSecurityController);
-        signalClusterQs.setNetworkController(mNetworkController);
-        final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
-        if (isAPhone) {
-            mNetworkController.addEmergencyLabelView(mHeader);
-        }
+            mNetworkController.addSignalCluster(signalCluster);
+            mNetworkController.addSignalCluster(signalClusterKeyguard);
+            mNetworkController.addSignalCluster(signalClusterQs);
+            signalCluster.setSecurityController(mSecurityController);
+            signalCluster.setNetworkController(mNetworkController);
+            signalClusterKeyguard.setSecurityController(mSecurityController);
+            signalClusterKeyguard.setNetworkController(mNetworkController);
+            signalClusterQs.setSecurityController(mSecurityController);
+            signalClusterQs.setNetworkController(mNetworkController);
+            final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
+            if (isAPhone) {
+                mNetworkController.addEmergencyLabelView(mHeader);
+            }
 
-        mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
-        mShowCarrierInPanel = (mCarrierLabel != null);
-        if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
-        if (mShowCarrierInPanel) {
-            mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
+            mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
+            mShowCarrierInPanel = (mCarrierLabel != null);
+            if (DEBUG) Log.v(TAG, "carrierlabel=" + mCarrierLabel + " show=" + mShowCarrierInPanel);
+            if (mShowCarrierInPanel) {
+                mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
 
-            // for mobile devices, we always show mobile connection info here (SPN/PLMN)
-            // for other devices, we show whatever network is connected
-            if (mNetworkController.hasMobileDataFeature()) {
-                mNetworkController.addMobileLabelView(mCarrierLabel);
-            } else {
-                mNetworkController.addCombinedLabelView(mCarrierLabel);
+                // for mobile devices, we always show mobile connection info here (SPN/PLMN)
+                // for other devices, we show whatever network is connected
+                if (mNetworkController.hasMobileDataFeature()) {
+                    mNetworkController.addMobileLabelView(mCarrierLabel);
+                } else {
+                    mNetworkController.addCombinedLabelView(mCarrierLabel);
+                }
             }
 
             // set up the dynamic hide/show of the label
@@ -860,12 +924,22 @@
         // Set up the quick settings tile panel
         mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
         if (mQSPanel != null) {
-            final QSTileHost qsh = new QSTileHost(mContext, this,
+            final QSTileHost qsh;
+            if (isMSim()) {
+                qsh = new QSTileHost(mContext, this,
+                    mBluetoothController, mLocationController, mRotationLockController,
+                    mMSimNetworkController, mZenModeController, mHotspotController,
+                    mCastController, mFlashlightController,
+                    mUserSwitcherController, mKeyguardMonitor,
+                    mSecurityController);
+            } else {
+                qsh = new QSTileHost(mContext, this,
                     mBluetoothController, mLocationController, mRotationLockController,
                     mNetworkController, mZenModeController, mHotspotController,
                     mCastController, mFlashlightController,
                     mUserSwitcherController, mKeyguardMonitor,
                     mSecurityController);
+            }
             mQSPanel.setHost(qsh);
             mQSPanel.setTiles(qsh.getTiles());
             mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
@@ -1628,12 +1702,23 @@
 
         // Emergency calls only is shown in the expanded header now.
         final boolean emergencyCallsShownElsewhere = true;
-        final boolean makeVisible =
+        final boolean makeVisible ;
+        if (isMSim()) {
+            makeVisible =
+            !(emergencyCallsShownElsewhere && mMSimNetworkController.isEmergencyOnly())
+            && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
+                    - mCarrierLabelHeight - mStatusBarHeaderHeight)
+            && mStackScroller.getVisibility() == View.VISIBLE
+            && mState != StatusBarState.KEYGUARD;
+        } else {
+            makeVisible =
             !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
             && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
                     - mCarrierLabelHeight - mStatusBarHeaderHeight)
             && mStackScroller.getVisibility() == View.VISIBLE
             && mState != StatusBarState.KEYGUARD;
+        }
+
 
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -2934,8 +3019,16 @@
             mGestureRec.dump(fd, pw, args);
         }
 
-        if (mNetworkController != null) {
-            mNetworkController.dump(fd, pw, args);
+        if (isMSim()) {
+            for(int i=0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+                if (mMSimNetworkController != null) {
+                    mMSimNetworkController.dump(fd, pw, args, i);
+                }
+            }
+        } else {
+            if (mNetworkController != null) {
+                mNetworkController.dump(fd, pw, args);
+            }
         }
         if (mBluetoothController != null) {
             mBluetoothController.dump(fd, pw, args);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 47e1ab5..9572bfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -28,9 +28,12 @@
 import android.os.UserHandle;
 import android.provider.Settings.Global;
 import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.CastController;
@@ -63,7 +66,7 @@
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
-    IccCardConstants.State mSimState = IccCardConstants.State.READY;
+    IccCardConstants.State[] mSimState;
 
     private boolean mZenVisible;
     private boolean mVolumeVisible;
@@ -119,6 +122,12 @@
         filter.addAction(Intent.ACTION_USER_SWITCHED);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
 
+        int numPhones = TelephonyManager.getDefault().getPhoneCount();
+        mSimState = new IccCardConstants.State[numPhones];
+        for (int i = 0; i < numPhones; i++) {
+            mSimState[i] = IccCardConstants.State.READY;
+        }
+
         // TTY status
         mService.setIcon(SLOT_TTY,  R.drawable.stat_sys_tty_mode, 0, null);
         mService.setIconVisibility(SLOT_TTY, false);
@@ -172,30 +181,41 @@
     }
 
     private final void updateSimState(Intent intent) {
+        IccCardConstants.State simState;
         String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.ABSENT;
-        }
-        else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.CARD_IO_ERROR;
-        }
-        else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.READY;
-        }
-        else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
-            final String lockedReason =
-                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PIN_REQUIRED;
+
+        // Obtain the subscription info from intent
+        long subId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
+        Log.d(TAG, "updateSimState for subId :" + subId);
+        int phoneId = SubscriptionManager.getPhoneId(subId);
+        Log.d(TAG, "updateSimState for phoneId :" + phoneId);
+        Log.d(TAG, "updateSimState for Slot :" + SubscriptionManager.getSlotId(subId));
+        if (phoneId >= 0 ) {
+            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+                simState = IccCardConstants.State.ABSENT;
             }
-            else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PUK_REQUIRED;
+            else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
+                simState = IccCardConstants.State.CARD_IO_ERROR;
             }
-            else {
-                mSimState = IccCardConstants.State.NETWORK_LOCKED;
+            else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+                simState = IccCardConstants.State.READY;
             }
-        } else {
-            mSimState = IccCardConstants.State.UNKNOWN;
+            else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+                final String lockedReason =
+                        intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                    simState = IccCardConstants.State.PIN_REQUIRED;
+                }
+                else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                    simState = IccCardConstants.State.PUK_REQUIRED;
+                }
+                else {
+                    simState = IccCardConstants.State.NETWORK_LOCKED;
+                }
+            } else {
+                simState = IccCardConstants.State.UNKNOWN;
+            }
+            mSimState[phoneId] = simState;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 8520f40..875c061 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.res.Resources;
+import android.telephony.TelephonyManager;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -45,7 +46,11 @@
     public void init() {
         mLeftSide = mView.findViewById(R.id.notification_icon_area);
         mStatusIcons = mView.findViewById(R.id.statusIcons);
-        mSignalCluster = mView.findViewById(R.id.signal_cluster);
+        if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+            mSignalCluster = mView.findViewById(R.id.msim_signal_cluster);
+        } else {
+            mSignalCluster = mView.findViewById(R.id.signal_cluster);
+        }
         mBattery = mView.findViewById(R.id.battery);
         mClock = mView.findViewById(R.id.clock);
         applyModeBackground(-1, getMode(), false /*animate*/);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index b0f3ea1..f961f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -26,6 +26,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
+import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.MathUtils;
 import android.util.TypedValue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkControllerImpl.java
new file mode 100644
index 0000000..2e5927f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkControllerImpl.java
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.net.wimax.WimaxManagerConstants;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubInfoRecord;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.cdma.EriInfo;
+import com.android.internal.util.AsyncChannel;
+
+import com.android.systemui.R;
+
+public class MSimNetworkControllerImpl extends NetworkControllerImpl {
+    // debug
+    static final String TAG = "StatusBar.MSimNetworkController";
+    static final boolean DEBUG = true;
+    static final boolean CHATTY = true; // additional diagnostics, but not logspew
+
+    // telephony
+    private TelephonyManager mPhone;
+    boolean[] mMSimDataConnected;
+    IccCardConstants.State[] mMSimState;
+    int[] mMSimDataActivity;
+    int[] mMSimDataServiceState;
+    ServiceState[] mMSimServiceState;
+    SignalStrength[] mMSimSignalStrength;
+    private PhoneStateListener[] mMSimPhoneStateListener;
+    private String[] mCarrierTextSub;
+
+    String[] mMSimNetworkName;
+    int[] mMSimPhoneSignalIconId;
+    int[] mMSimLastPhoneSignalIconId;
+    private int[] mMSimIconId;
+    int[] mMSimDataDirectionIconId; // data + data direction on phones
+    int[] mMSimDataSignalIconId;
+    int[] mMSimDataTypeIconId;
+    int[] mMSimMobileActivityIconId; // overlay arrows for data direction
+
+    String[] mMSimContentDescriptionPhoneSignal;
+    String[] mMSimContentDescriptionCombinedSignal;
+    String[] mMSimContentDescriptionDataType;
+
+    int[] mMSimLastDataDirectionIconId;
+    int[] mMSimLastCombinedSignalIconId;
+    int[] mMSimLastDataTypeIconId;
+    int[] mMSimcombinedSignalIconId;
+    int[] mMSimcombinedActivityIconId;
+    private int mDefaultPhoneId;
+    boolean[] mShowSpn;
+    boolean[] mShowPlmn;
+    String[] mSpn;
+    String[] mPlmn;
+    int mPhoneCount = 0;
+    int PHONE_ID1 = PhoneConstants.PHONE_ID1;
+    int PHONE_ID2 = PhoneConstants.PHONE_ID2;
+    private HashMap<Long, Integer> mSubIdPhoneIdMap;
+    ArrayList<MSimSignalCluster> mSimSignalClusters = new ArrayList<MSimSignalCluster>();
+    ArrayList<TextView> mSubsLabelViews = new ArrayList<TextView>();
+
+    public interface MSimSignalCluster {
+        void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
+        void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
+                String contentDescription, String typeContentDescription,
+                int phoneId);
+        void setIsAirplaneMode(boolean is, int airplaneIcon);
+    }
+
+    /**
+     * Construct this controller object and register for updates.
+     */
+    public MSimNetworkControllerImpl(Context context) {
+        super(context);
+        int numPhones = TelephonyManager.getDefault().getPhoneCount();
+        Slog.d(TAG, "registerPhoneStateListener numPhones: " + numPhones);
+        mMSimSignalStrength = new SignalStrength[numPhones];
+        mMSimDataServiceState = new int[numPhones];
+        mMSimServiceState = new ServiceState[numPhones];
+        mMSimState = new IccCardConstants.State[numPhones];
+        mMSimIconId = new int[numPhones];
+        mMSimPhoneSignalIconId = new int[numPhones];
+        mMSimDataTypeIconId = new int[numPhones];
+        mMSimMobileActivityIconId = new int[numPhones];
+        mMSimContentDescriptionPhoneSignal = new String[numPhones];
+        mMSimLastPhoneSignalIconId = new int[numPhones];
+        mMSimNetworkName = new String[numPhones];
+        mMSimLastDataTypeIconId = new int[numPhones];
+        mMSimDataConnected = new boolean[numPhones];
+        mMSimDataSignalIconId = new int[numPhones];
+        mMSimDataDirectionIconId = new int[numPhones];
+        mMSimLastDataDirectionIconId = new int[numPhones];
+        mMSimLastCombinedSignalIconId = new int[numPhones];
+        mMSimcombinedSignalIconId = new int[numPhones];
+        mMSimcombinedActivityIconId = new int[numPhones];
+        mMSimDataActivity = new int[numPhones];
+        mMSimContentDescriptionCombinedSignal = new String[numPhones];
+        mMSimContentDescriptionDataType = new String[numPhones];
+        mCarrierTextSub = new String[numPhones];
+        mShowSpn = new boolean[numPhones];
+        mShowPlmn = new boolean[numPhones];
+        mSpn = new String[numPhones];
+        mPlmn = new String[numPhones];
+
+
+        for (int i=0; i < numPhones; i++) {
+            mMSimSignalStrength[i] = new SignalStrength();
+            mMSimServiceState[i] = new ServiceState();
+            mMSimState[i] = IccCardConstants.State.READY;
+            // phone_signal
+            mMSimPhoneSignalIconId[i] = 0;
+            mMSimLastPhoneSignalIconId[i] = -1;
+            mMSimLastDataTypeIconId[i] = -1;
+            mMSimDataConnected[i] = false;
+            mMSimLastDataDirectionIconId[i] = -1;
+            mMSimLastCombinedSignalIconId[i] = -1;
+            mMSimcombinedSignalIconId[i] = 0;
+            mMSimcombinedActivityIconId[i] = 0;
+            mMSimDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
+            mMSimNetworkName[i] = mNetworkNameDefault;
+            mMSimDataServiceState[i] = ServiceState.STATE_OUT_OF_SERVICE;
+        }
+
+        mDefaultPhoneId = SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubId());
+        mDataConnected = mMSimDataConnected[mDefaultPhoneId];
+        mSimState = mMSimState[mDefaultPhoneId];
+        mDataActivity = mMSimDataActivity[mDefaultPhoneId];
+        mDataServiceState = mMSimDataServiceState[mDefaultPhoneId];
+        mServiceState = mMSimServiceState[mDefaultPhoneId];
+        mSignalStrength = mMSimSignalStrength[mDefaultPhoneId];
+        mPhoneStateListener = mMSimPhoneStateListener[mDefaultPhoneId];
+
+        mNetworkName = mMSimNetworkName[mDefaultPhoneId];
+        mPhoneSignalIconId = mMSimPhoneSignalIconId[mDefaultPhoneId];
+        mLastPhoneSignalIconId = mMSimLastPhoneSignalIconId[mDefaultPhoneId];
+        // data + data direction on phones
+        mDataDirectionIconId = mMSimDataDirectionIconId[mDefaultPhoneId];
+        mDataSignalIconId = mMSimDataSignalIconId[mDefaultPhoneId];
+        mDataTypeIconId = mMSimDataTypeIconId[mDefaultPhoneId];
+
+        mContentDescriptionPhoneSignal = mMSimContentDescriptionPhoneSignal[mDefaultPhoneId];
+        mContentDescriptionCombinedSignal = mMSimContentDescriptionCombinedSignal[
+                mDefaultPhoneId];
+        mContentDescriptionDataType = mMSimContentDescriptionDataType[mDefaultPhoneId];
+
+        mLastDataDirectionIconId = mMSimLastDataDirectionIconId[mDefaultPhoneId];
+        mLastCombinedSignalIconId = mMSimLastCombinedSignalIconId[mDefaultPhoneId];
+        mLastDataTypeIconId = mMSimLastDataTypeIconId[mDefaultPhoneId];
+    }
+
+    @Override
+    protected void createWifiHandler() {
+        // wifi
+        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        Handler handler = new MSimWifiHandler();
+        mWifiChannel = new AsyncChannel();
+        Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
+        if (wifiMessenger != null) {
+            mWifiChannel.connect(mContext, handler, wifiMessenger);
+        }
+    }
+
+    @Override
+    protected void registerPhoneStateListener(Context context) {
+        // telephony
+        mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+        //List<SubInfoRecord> subInfoList = SubscriptionManager.getActivatedSubInfoList(context);
+        //if (subInfoList != null) {
+            //int subCount = subInfoList.size();
+            mSubIdPhoneIdMap = new HashMap<Long, Integer>();
+            mPhoneCount = TelephonyManager.getDefault().getPhoneCount();
+             Slog.d(TAG, "registerPhoneStateListener: " + mPhoneCount);
+            mMSimPhoneStateListener = new PhoneStateListener[mPhoneCount];
+            for (int i=0; i < mPhoneCount; i++) {
+                long[] subIdtemp = SubscriptionManager.getSubId(i);
+                if (subIdtemp != null) {
+                    long subId = subIdtemp[0];
+                    Slog.d(TAG, "registerPhoneStateListener subId: "+ subId);
+                    Slog.d(TAG, "registerPhoneStateListener slotId: "+ i);
+                    //if (subInfoList.get(i).mSubId >= 0) {
+                    if (subId > 0) {
+                        mSubIdPhoneIdMap.put(subId, i);
+                        mMSimPhoneStateListener[i] = getPhoneStateListener(subId,
+                                i);
+                        mPhone.listen(mMSimPhoneStateListener[i],
+                                        PhoneStateListener.LISTEN_SERVICE_STATE
+                                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+                                        | PhoneStateListener.LISTEN_CALL_STATE
+                                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+                    } else {
+                        mMSimPhoneStateListener[i] = null;
+                    }
+                }
+            }
+        //}
+    }
+    private int getPhoneId(long subId) {
+        int phoneId;
+        phoneId = SubscriptionManager.getPhoneId(subId);
+        Slog.d(TAG, "getPhoneId phoneId: " +phoneId);
+        return phoneId;
+    }
+
+    private void unregisterPhoneStateListener() {
+        for (int i = 0 ; i < mPhoneCount ; i++) {
+            if (mMSimPhoneStateListener[i] != null) {
+                mPhone.listen(mMSimPhoneStateListener[i], PhoneStateListener.LISTEN_NONE);
+            }
+        }
+    }
+
+    public void addSignalCluster(MSimSignalCluster cluster, int phoneId) {
+        mSimSignalClusters.add(cluster);
+        refreshSignalCluster(cluster, phoneId);
+    }
+
+    public void refreshSignalCluster(MSimSignalCluster cluster, int phoneId) {
+        cluster.setWifiIndicators(
+                // only show wifi in the cluster if connected or if wifi-only
+                mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
+                mWifiIconId,
+                mContentDescriptionWifi);
+        cluster.setMobileDataIndicators(
+                mHasMobileDataFeature,
+                mMSimPhoneSignalIconId[phoneId],
+                mMSimDataTypeIconId[phoneId],
+                mMSimContentDescriptionPhoneSignal[phoneId],
+                mMSimContentDescriptionDataType[phoneId],
+                phoneId);
+        if (mIsWimaxEnabled && mWimaxConnected) {
+            // wimax is special
+            cluster.setMobileDataIndicators(
+                    true,
+                    mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
+                    mMSimDataTypeIconId[phoneId],
+                    mContentDescriptionWimax,
+                    mMSimContentDescriptionDataType[phoneId],
+                    phoneId);
+        } else {
+            // normal mobile data
+            cluster.setMobileDataIndicators(
+                    mHasMobileDataFeature,
+                    mShowPhoneRSSIForData ? mMSimPhoneSignalIconId[phoneId]
+                        : mMSimDataSignalIconId[phoneId],
+                    mMSimDataTypeIconId[phoneId],
+                    mMSimContentDescriptionPhoneSignal[phoneId],
+                    mMSimContentDescriptionDataType[phoneId],
+                    phoneId);
+        }
+        cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
+                || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
+                || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+            updateWifiState(intent);
+            refreshViews(mDefaultPhoneId);
+        } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+            updateSimState(intent);
+            for (int sub = 0; sub < TelephonyManager.getDefault().getPhoneCount(); sub++) {
+                updateDataIcon(sub);
+                refreshViews(sub);
+            }
+        } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
+            final long subId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
+            Slog.d(TAG, "Received SPN update on subId :" + subId);
+            Integer phoneId = getPhoneId(subId);
+            Slog.d(TAG, "Received SPN update on phoneId :" + phoneId);
+            mShowSpn[phoneId] = intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false);
+            mSpn[phoneId] = intent.getStringExtra(TelephonyIntents.EXTRA_SPN);
+            mShowPlmn[phoneId] = intent.getBooleanExtra(
+                    TelephonyIntents.EXTRA_SHOW_PLMN, false);
+            mPlmn[phoneId] = intent.getStringExtra(TelephonyIntents.EXTRA_PLMN);
+
+            updateNetworkName(mShowSpn[phoneId], mSpn[phoneId], mShowPlmn[phoneId],
+                    mPlmn[phoneId], phoneId);
+            updateCarrierText(phoneId);
+            refreshViews(phoneId);
+        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
+                 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+            updateConnectivity(intent);
+            refreshViews(mDefaultPhoneId);
+        } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+            refreshViews(mDefaultPhoneId);
+        } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
+            updateAirplaneMode();
+            for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+                updateCarrierText(i);
+            }
+            refreshViews(mDefaultPhoneId);
+        } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) ||
+                action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) ||
+                action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
+            updateWimaxState(intent);
+            refreshViews(mDefaultPhoneId);
+        } else if (action.equals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED)) {
+                unregisterPhoneStateListener();
+                registerPhoneStateListener(mContext);
+                mDefaultPhoneId = SubscriptionManager.getPhoneId(
+                        SubscriptionManager.getDefaultSubId());
+                for (int i=0 ; i < mPhoneCount ; i++) {
+                    updateCarrierText(i);
+                    updateTelephonySignalStrength(i);
+                    updateDataNetType(i);
+                    updateDataIcon(i);
+                    refreshViews(i);
+                }
+        }
+    }
+
+    public void addSubsLabelView(TextView v) {
+        mSubsLabelViews.add(v);
+    }
+
+    private void updateCarrierText(int sub) {
+        int textResId = 0;
+        if (mAirplaneMode) {
+            textResId = com.android.internal.R.string.lockscreen_airplane_mode_on;
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "updateCarrierText for sub:" + sub + " simState =" + mMSimState[sub]);
+            }
+
+            switch (mMSimState[sub]) {
+                case ABSENT:
+                case UNKNOWN:
+                case NOT_READY:
+                    textResId = com.android.internal.R.string.lockscreen_missing_sim_message_short;
+                    break;
+                case PIN_REQUIRED:
+                    textResId = com.android.internal.R.string.lockscreen_sim_locked_message;
+                    break;
+                case PUK_REQUIRED:
+                    textResId = com.android.internal.R.string.lockscreen_sim_puk_locked_message;
+                    break;
+                case READY:
+                    // If the state is ready, set the text as network name.
+                    mCarrierTextSub[sub] = mMSimNetworkName[sub];
+                    break;
+                case PERM_DISABLED:
+                    textResId = com.android.internal.
+                            R.string.lockscreen_permanent_disabled_sim_message_short;
+                    break;
+                case CARD_IO_ERROR:
+                    textResId = com.android.internal.R.string.lockscreen_sim_error_message_short;
+                    break;
+                default:
+                    textResId = com.android.internal.R.string.lockscreen_missing_sim_message_short;
+                    break;
+            }
+        }
+
+        if (textResId != 0) {
+            mCarrierTextSub[sub] = mContext.getString(textResId);
+        }
+    }
+
+    private void setCarrierText() {
+        String carrierName = mCarrierTextSub[PHONE_ID1];
+        for (int i = 1; i < mPhoneCount; i++) {
+            carrierName = carrierName + "    " + mCarrierTextSub[i];
+        }
+
+        for (int i = 0; i < mSubsLabelViews.size(); i++) {
+            TextView v = mSubsLabelViews.get(i);
+            v.setText(carrierName);
+        }
+    }
+
+
+    // ===== Telephony ==============================================================
+
+    private PhoneStateListener getPhoneStateListener(long subId, int slotId) {
+        PhoneStateListener mMSimPhoneStateListener = new PhoneStateListener(subId) {
+            @Override
+            public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+                if (DEBUG) {
+                    Slog.d(TAG, "onSignalStrengthsChanged received on phoneId :"
+                        + getPhoneId(mSubId) + "signalStrength=" + signalStrength +
+                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
+                }
+                mMSimSignalStrength[getPhoneId(mSubId)] = signalStrength;
+                updateTelephonySignalStrength(getPhoneId(mSubId));
+                refreshViews(getPhoneId(mSubId));
+            }
+
+            @Override
+            public void onServiceStateChanged(ServiceState state) {
+                int phoneId = getPhoneId(mSubId);
+                if (DEBUG) {
+                    Slog.d(TAG, "onServiceStateChanged received on phoneId :"
+                        + phoneId + "state=" + state.getState());
+                }
+                mMSimServiceState[phoneId] = state;
+                if (SystemProperties.getBoolean("ro.config.combined_signal", true)) {
+                    /*
+                     * if combined_signal is set to true only then consider data
+                     * service state for signal display
+                     */
+                    mMSimDataServiceState[phoneId] =
+                        mMSimServiceState[phoneId].getDataRegState();
+                    if (DEBUG) {
+                        Slog.d(TAG, "Combining data service state " +
+                                mMSimDataServiceState[phoneId] + " for signal");
+                    }
+                }
+                updateTelephonySignalStrength(phoneId);
+                updateDataNetType(phoneId);
+                updateDataIcon(phoneId);
+                updateNetworkName(mShowSpn[phoneId], mSpn[phoneId],
+                                mShowPlmn[phoneId], mPlmn[phoneId], phoneId);
+                updateCarrierText(phoneId);
+
+                refreshViews(phoneId);
+            }
+
+            @Override
+            public void onCallStateChanged(int state, String incomingNumber) {
+                int phoneId = getPhoneId(mSubId);
+                if (DEBUG) {
+                    Slog.d(TAG, "onCallStateChanged received on phoneId :"
+                    + phoneId + "state=" + state);
+                }
+                // In cdma, if a voice call is made, RSSI should switch to 1x.
+                if (isCdma(phoneId)) {
+                    updateTelephonySignalStrength(phoneId);
+                    refreshViews(phoneId);
+                }
+            }
+
+            @Override
+            public void onDataConnectionStateChanged(int state, int networkType) {
+                int phoneId = getPhoneId(mSubId);
+                if (DEBUG) {
+                    Slog.d(TAG, "onDataConnectionStateChanged received on phoneId :"
+                    + phoneId + " subid: " + mSubId+ "state=" + state + " type=" + networkType);
+                }
+
+                // DSDS case: Data is active only on DDS. Ignore the Data Connection
+                // State changed notifications of the other NON-DDS.
+                Slog.d(TAG, "onDataConnectionStateChanged getDefaultDataSubId :" +
+                        SubscriptionManager.getDefaultDataSubId());
+                if ( mSubId ==
+                        SubscriptionManager.getDefaultDataSubId()) {
+                    mDataState = state;
+                    mDataNetType = networkType;
+                }
+                updateDataNetType(phoneId);
+                updateDataIcon(phoneId);
+                refreshViews(phoneId);
+            }
+
+            @Override
+            public void onDataActivity(int direction) {
+                int phoneId = getPhoneId(mSubId);
+                if (DEBUG) {
+                    Slog.d(TAG, "onDataActivity received on phoneId :"
+                        + phoneId + "direction=" + direction);
+                }
+                mMSimDataActivity[phoneId] = direction;
+                mDataActivity = direction;
+                updateDataIcon(phoneId);
+                refreshViews(phoneId);
+            }
+        };
+        return mMSimPhoneStateListener;
+    }
+
+    // ===== Wifi ===================================================================
+
+    class MSimWifiHandler extends WifiHandler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case WifiManager.DATA_ACTIVITY_NOTIFICATION:
+                    if (msg.arg1 != mWifiActivity) {
+                        mWifiActivity = msg.arg1;
+                        int dataSub = SubscriptionManager.getPhoneId(
+                                SubscriptionManager.getDefaultDataSubId());
+                        refreshViews(dataSub);
+                    }
+                    break;
+                default:
+                    super.handleMessage(msg);
+                    break;
+            }
+        }
+    }
+
+    @Override
+    protected void updateSimState(Intent intent) {
+        IccCardConstants.State simState;
+        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+        // Obtain the phoneId info from intent.
+        //long subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
+        int phoneId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
+        //Integer sub = mSubIdPhoneIdMap.get(subId);
+        Slog.d(TAG, "updateSimState for phoneId :" + phoneId);
+        if (phoneId >= 0) {
+            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+                simState = IccCardConstants.State.ABSENT;
+            }
+            else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+                simState = IccCardConstants.State.READY;
+            }
+            else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+                final String lockedReason = intent.getStringExtra(IccCardConstants.
+                                                                INTENT_KEY_LOCKED_REASON);
+                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                    simState = IccCardConstants.State.PIN_REQUIRED;
+                }
+                else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                    simState = IccCardConstants.State.PUK_REQUIRED;
+                }
+                else {
+                    simState = IccCardConstants.State.NETWORK_LOCKED;
+                }
+            } else {
+                simState = IccCardConstants.State.UNKNOWN;
+            }
+            // Update the sim state and carrier text.
+            if (simState != IccCardConstants.State.UNKNOWN && simState != mMSimState[phoneId]) {
+                mMSimState[phoneId] = simState;
+                updateCarrierText(phoneId);
+                Slog.d(TAG, "updateSimState simState =" + mMSimState[phoneId]);
+            }
+            updateDataIcon(phoneId);
+        }
+    }
+
+    private boolean isCdma(int phoneId) {
+        return (mMSimSignalStrength[phoneId] != null) &&
+                !mMSimSignalStrength[phoneId].isGsm();
+    }
+
+    private boolean hasService(int phoneId) {
+        ServiceState ss = mMSimServiceState[phoneId];
+        if (ss != null) {
+            switch (ss.getState()) {
+                case ServiceState.STATE_OUT_OF_SERVICE:
+                case ServiceState.STATE_POWER_OFF:
+                    return false;
+                default:
+                    return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private final void updateTelephonySignalStrength(int phoneId) {
+        Slog.d(TAG, "updateTelephonySignalStrength: phoneId =" + phoneId);
+        int dataSub = SubscriptionManager.getPhoneId(
+                SubscriptionManager.getDefaultDataSubId());
+        if (!hasService(phoneId) &&
+                (mMSimDataServiceState[phoneId] != ServiceState.STATE_IN_SERVICE)) {
+            if (DEBUG) Slog.d(TAG, " No service");
+            mMSimPhoneSignalIconId[phoneId] = R.drawable.stat_sys_signal_null;
+            mMSimDataSignalIconId[phoneId] = R.drawable.stat_sys_signal_null;
+            if (phoneId == dataSub) {
+                mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
+            }
+        } else {
+            if (mMSimSignalStrength[phoneId] == null || (mMSimServiceState == null)) {
+                if (DEBUG) {
+                    Slog.d(TAG, " Null object, mMSimSignalStrength= "
+                            + mMSimSignalStrength[phoneId]
+                            + " mMSimServiceState " + mMSimServiceState[phoneId]);
+                }
+                mMSimPhoneSignalIconId[phoneId] = R.drawable.stat_sys_signal_null;
+                mMSimDataSignalIconId[phoneId] = R.drawable.stat_sys_signal_null;
+                mMSimContentDescriptionPhoneSignal[phoneId] = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
+                if (phoneId == dataSub) {
+                    mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
+                }
+            } else {
+                int iconLevel;
+                int[] iconList;
+                if (isCdma(phoneId) && mAlwaysShowCdmaRssi) {
+                    mLastSignalLevel = iconLevel = mMSimSignalStrength[phoneId].getCdmaLevel();
+                    if(DEBUG) Slog.d(TAG, "mAlwaysShowCdmaRssi= " + mAlwaysShowCdmaRssi
+                            + " set to cdmaLevel= "
+                            + mMSimSignalStrength[phoneId].getCdmaLevel()
+                            + " instead of level= " + mMSimSignalStrength[phoneId].getLevel());
+                } else {
+                    mLastSignalLevel = iconLevel = mMSimSignalStrength[phoneId].getLevel();
+                }
+
+                // Though mPhone is a Manager, this call is not an IPC
+                if ((isCdma(phoneId) && isCdmaEri(phoneId)) ||
+                        mPhone.isNetworkRoaming(phoneId)) {
+                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
+                } else {
+                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
+                }
+
+                Slog.d(TAG, "updateTelephonySignalStrength iconList = " + iconList + "iconLevel = "
+                        + iconLevel + " mInetCondition = " + mInetCondition);
+                mMSimPhoneSignalIconId[phoneId] = iconList[iconLevel];
+                mMSimContentDescriptionPhoneSignal[phoneId] = mContext.getString(
+                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
+                if (phoneId == dataSub) {
+                    mQSPhoneSignalIconId = TelephonyIcons
+                            .QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel];
+                }
+
+                mMSimDataSignalIconId[phoneId] = TelephonyIcons
+                        .DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
+            }
+        }
+    }
+
+    private final void updateDataNetType(int phoneId) {
+        // DSDS case: Data is active only on DDS. Clear the icon for NON-DDS
+        int dataSub = SubscriptionManager.getPhoneId(
+                SubscriptionManager.getDefaultDataSubId());
+        if (phoneId != dataSub) {
+            Slog.d(TAG,"updateDataNetType: phoneId" + phoneId
+                    + " is not DDS(=SUB" + dataSub + ")!");
+            mMSimDataTypeIconId[phoneId] = 0;
+        } else {
+            mNetworkName = mMSimNetworkName[phoneId];
+            if (mIsWimaxEnabled && mWimaxConnected) {
+                // wimax is a special 4g network not handled by telephony
+                mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+                mMSimDataTypeIconId[phoneId] = R.drawable.stat_sys_data_fully_connected_4g;
+                mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[mInetCondition];
+                mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                        R.string.accessibility_data_connection_4g);
+            } else {
+                Slog.d(TAG,"updateDataNetType sub = " + phoneId
+                        + " mDataNetType = " + mDataNetType);
+                switch (mDataNetType) {
+                    case TelephonyManager.NETWORK_TYPE_UNKNOWN:
+                        if (DEBUG) {
+                            Slog.e(TAG, "updateDataNetType NETWORK_TYPE_UNKNOWN");
+                        }
+                        if (!mShowAtLeastThreeGees) {
+                            mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] = 0;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_gprs);
+                            break;
+                        } else {
+                            // fall through
+                        }
+                    case TelephonyManager.NETWORK_TYPE_EDGE:
+                        if (!mShowAtLeastThreeGees) {
+                            mDataIconList = TelephonyIcons.DATA_E[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] =
+                                    R.drawable.stat_sys_data_fully_connected_e;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_edge);
+                            break;
+                        } else {
+                            // fall through
+                        }
+                    case TelephonyManager.NETWORK_TYPE_UMTS:
+                    //case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+                        mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
+                        mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_3g;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                        mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                R.string.accessibility_data_connection_3g);
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_HSDPA:
+                    case TelephonyManager.NETWORK_TYPE_HSUPA:
+                    case TelephonyManager.NETWORK_TYPE_HSPA:
+                    case TelephonyManager.NETWORK_TYPE_HSPAP:
+                        if (mHspaDataDistinguishable) {
+                            mDataIconList = TelephonyIcons.DATA_H[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] =
+                                    R.drawable.stat_sys_data_fully_connected_h;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_3_5g);
+                        } else {
+                            mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] =
+                                    R.drawable.stat_sys_data_fully_connected_3g;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_3g);
+                        }
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_CDMA:
+                        // display 1xRTT for IS95A/B
+                        mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
+                        mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_1x;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[mInetCondition];
+                        mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                R.string.accessibility_data_connection_cdma);
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_1xRTT:
+                        mDataIconList = TelephonyIcons.DATA_1X[mInetCondition];
+                        mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_1x;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[mInetCondition];
+                        mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                R.string.accessibility_data_connection_cdma);
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
+                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
+                    case TelephonyManager.NETWORK_TYPE_EVDO_B:
+                    case TelephonyManager.NETWORK_TYPE_EHRPD:
+                        mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
+                        mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_3g;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                        mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                R.string.accessibility_data_connection_3g);
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_LTE:
+                        mDataIconList = TelephonyIcons.DATA_4G[mInetCondition];
+                        mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_4g;
+                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[mInetCondition];
+                        mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                R.string.accessibility_data_connection_4g);
+                        break;
+                    case TelephonyManager.NETWORK_TYPE_GPRS:
+                        if (!mShowAtLeastThreeGees) {
+                            mDataIconList = TelephonyIcons.DATA_G[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] =
+                                    R.drawable.stat_sys_data_fully_connected_g;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_gprs);
+                        } else {
+                            mDataIconList = TelephonyIcons.DATA_3G[mInetCondition];
+                            mMSimDataTypeIconId[phoneId] =
+                                R.drawable.stat_sys_data_fully_connected_3g;
+                            mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[mInetCondition];
+                            mMSimContentDescriptionDataType[phoneId] = mContext.getString(
+                                    R.string.accessibility_data_connection_3g);
+                        }
+                        break;
+                    default:
+                        if (DEBUG) {
+                            Slog.e(TAG, "updateDataNetType unknown radio:" + mDataNetType);
+                        }
+                        mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+                        mQSDataTypeIconId = mMSimDataTypeIconId[phoneId] = 0;
+                        break;
+                }
+            }
+        }
+
+        if (isCdma(phoneId)) {
+            if (isCdmaEri(phoneId)) {
+                mMSimDataTypeIconId[phoneId] = R.drawable.stat_sys_data_fully_connected_roam;
+                if (phoneId == dataSub) {
+                    mQSDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                }
+            }
+        } else if (mPhone.isNetworkRoaming(phoneId)) {
+            mMSimDataTypeIconId[phoneId] = R.drawable.stat_sys_data_fully_connected_roam;
+            if (phoneId == dataSub) {
+                mQSDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+            }
+        }
+    }
+
+    boolean isCdmaEri(int phoneId) {
+        if ((mMSimServiceState[phoneId] != null)
+                && (hasService(phoneId) || (mMSimDataServiceState[phoneId]
+                == ServiceState.STATE_IN_SERVICE))) {
+            final int iconIndex = mMSimServiceState[phoneId].getCdmaEriIconIndex();
+            if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
+                final int iconMode = mMSimServiceState[phoneId].getCdmaEriIconMode();
+                if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
+                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private final void updateDataIcon(int phoneId) {
+        Slog.d(TAG,"updateDataIcon phoneId =" + phoneId);
+        int iconId = 0;
+        boolean visible = true;
+        int dataSub = SubscriptionManager.getPhoneId(
+                SubscriptionManager.getDefaultDataSubId());
+
+        Slog.d(TAG,"updateDataIcon dataSub =" + dataSub);
+        // DSDS case: Data is active only on DDS. Clear the icon for NON-DDS
+        if (phoneId != dataSub) {
+            mMSimDataConnected[phoneId] = false;
+            Slog.d(TAG,"updateDataIconi: phoneId" + phoneId
+                     + " is not DDS.  Clear the mMSimDataConnected Flag and return");
+            return;
+        }
+
+        Slog.d(TAG,"updateDataIcon  when SimState =" + mMSimState[phoneId]);
+        if (mDataNetType == TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+            // If data network type is unknown do not display data icon
+            visible = false;
+        } else if (!isCdma(phoneId)) {
+             Slog.d(TAG,"updateDataIcon  when gsm mMSimState =" + mMSimState[phoneId]);
+            // GSM case, we have to check also the sim state
+            if (mMSimState[phoneId] == IccCardConstants.State.READY ||
+                mMSimState[phoneId] == IccCardConstants.State.UNKNOWN) {
+                mNoSim = false;
+                if (mDataState == TelephonyManager.DATA_CONNECTED) {
+                    switch (mMSimDataActivity[phoneId]) {
+                        case TelephonyManager.DATA_ACTIVITY_IN:
+                            iconId = mDataIconList[1];
+                            break;
+                        case TelephonyManager.DATA_ACTIVITY_OUT:
+                            iconId = mDataIconList[2];
+                            break;
+                        case TelephonyManager.DATA_ACTIVITY_INOUT:
+                            iconId = mDataIconList[3];
+                            break;
+                        default:
+                            iconId = mDataIconList[0];
+                            break;
+                    }
+                    mMSimDataDirectionIconId[phoneId] = iconId;
+                } else {
+                    iconId = 0;
+                    visible = false;
+                }
+            } else {
+                Slog.d(TAG,"updateDataIcon when no sim");
+                mNoSim = true;
+                iconId = R.drawable.stat_sys_no_sim;
+                visible = false; // no SIM? no data
+            }
+        } else {
+            // CDMA case, mMSimDataActivity can be also DATA_ACTIVITY_DORMANT
+            if (mDataState == TelephonyManager.DATA_CONNECTED) {
+                switch (mMSimDataActivity[phoneId]) {
+                    case TelephonyManager.DATA_ACTIVITY_IN:
+                        iconId = mDataIconList[1];
+                        break;
+                    case TelephonyManager.DATA_ACTIVITY_OUT:
+                        iconId = mDataIconList[2];
+                        break;
+                    case TelephonyManager.DATA_ACTIVITY_INOUT:
+                        iconId = mDataIconList[3];
+                        break;
+                    case TelephonyManager.DATA_ACTIVITY_DORMANT:
+                    default:
+                        iconId = mDataIconList[0];
+                        break;
+                }
+            } else {
+                iconId = 0;
+                visible = false;
+            }
+        }
+
+        mMSimDataDirectionIconId[phoneId] = iconId;
+        mMSimDataConnected[phoneId] = visible;
+        mDataConnected = visible;
+        Slog.d(TAG,"updateDataIcon when mMSimDataConnected =" + mMSimDataConnected[phoneId]);
+    }
+
+    void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn,
+            int phoneId) {
+        if (DEBUG) {
+            Slog.d(TAG, "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
+        }
+        StringBuilder str = new StringBuilder();
+        boolean something = false;
+        if (showPlmn && plmn != null) {
+            str.append(plmn);
+            something = true;
+        }
+        if (showSpn && spn != null) {
+            if (something) {
+                str.append(mNetworkNameSeparator);
+            }
+            str.append(spn);
+            something = true;
+        }
+        if (something) {
+            mMSimNetworkName[phoneId] = str.toString();
+        } else {
+            mMSimNetworkName[phoneId] = mNetworkNameDefault;
+        }
+        Slog.d(TAG, "mMSimNetworkName[phoneId] " + mMSimNetworkName[phoneId]
+                                                      + "phoneId " + phoneId);
+    }
+
+    // ===== Full or limited Internet connectivity ==================================
+    @Override
+    protected void updateConnectivity(Intent intent) {
+        if (CHATTY) {
+            Slog.d(TAG, "updateConnectivity: intent=" + intent);
+        }
+
+        final ConnectivityManager connManager = (ConnectivityManager) mContext
+                .getSystemService(Context.CONNECTIVITY_SERVICE);
+        final NetworkInfo info = connManager.getActiveNetworkInfo();
+
+        // Are we connected at all, by any interface?
+        mConnected = info != null && info.isConnected();
+        if (mConnected) {
+            mConnectedNetworkType = info.getType();
+            mConnectedNetworkTypeName = info.getTypeName();
+        } else {
+            mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+            mConnectedNetworkTypeName = null;
+        }
+
+        int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
+
+        if (CHATTY) {
+            Slog.d(TAG, "updateConnectivity: networkInfo=" + info);
+            Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
+        }
+
+        mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
+        if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
+            mBluetoothTethered = info.isConnected();
+        } else {
+            mBluetoothTethered = false;
+        }
+
+        // We want to update all the icons, all at once, for any condition change
+        updateWimaxIcons();
+        for (int sub = 0; sub < TelephonyManager.getDefault().getPhoneCount(); sub++) {
+            updateDataNetType(sub);
+            updateDataIcon(sub);
+            updateTelephonySignalStrength(sub);
+        }
+        updateWifiIcons();
+    }
+
+    // ===== Update the views =======================================================
+
+    protected void refreshViews(int phoneId) {
+        Context context = mContext;
+
+        String combinedLabel = "";
+        String mobileLabel = "";
+        String wifiLabel = "";
+        int N;
+        Slog.d(TAG,"refreshViews phoneId =" + phoneId + "mMSimDataConnected ="
+                + mMSimDataConnected[phoneId]);
+        Slog.d(TAG,"refreshViews mMSimDataActivity =" + mMSimDataActivity[phoneId]);
+        int dataSub = SubscriptionManager.getPhoneId(
+                SubscriptionManager.getDefaultDataSubId());
+        if (!mHasMobileDataFeature) {
+            mMSimDataSignalIconId[phoneId] = mMSimPhoneSignalIconId[phoneId] = 0;
+            mobileLabel = "";
+        } else {
+            // We want to show the carrier name if in service and either:
+            //   - We are connected to mobile data, or
+            //   - We are not connected to mobile data, as long as the *reason* packets are not
+            //     being routed over that link is that we have better connectivity via wifi.
+            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
+            // is connected, we show nothing.
+            // Otherwise (nothing connected) we show "No internet connection".
+
+            if (mMSimDataConnected[phoneId]) {
+                mobileLabel = mMSimNetworkName[phoneId];
+            } else if (mConnected) {
+                if (hasService(phoneId)) {
+                    mobileLabel = mMSimNetworkName[phoneId];
+                } else {
+                    mobileLabel = "";
+                }
+            } else {
+                mobileLabel
+                    = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+            }
+
+            // Now for things that should only be shown when actually using mobile data.
+            if (mMSimDataConnected[phoneId]) {
+                mMSimcombinedSignalIconId[phoneId] = mMSimDataSignalIconId[phoneId];
+
+                combinedLabel = mobileLabel;
+                mMSimcombinedActivityIconId[phoneId] = mMSimMobileActivityIconId[phoneId];
+                // set by updateDataIcon()
+                mMSimcombinedSignalIconId[phoneId] = mMSimDataSignalIconId[phoneId];
+                mMSimContentDescriptionCombinedSignal[phoneId] =
+                        mMSimContentDescriptionDataType[phoneId];
+            } else {
+                mMSimMobileActivityIconId[phoneId] = 0;
+            }
+        }
+
+        if (mWifiConnected) {
+            if (mWifiSsid == null) {
+                wifiLabel = context.getString(
+                        R.string.status_bar_settings_signal_meter_wifi_nossid);
+            } else {
+                wifiLabel = mWifiSsid;
+                if (DEBUG) {
+                    wifiLabel += "xxxxXXXXxxxxXXXX";
+                }
+            }
+            combinedLabel = wifiLabel;
+            mMSimcombinedSignalIconId[phoneId] = mWifiIconId; // set by updateWifiIcons()
+            mMSimContentDescriptionCombinedSignal[phoneId] = mContentDescriptionWifi;
+        } else {
+            if (mHasMobileDataFeature) {
+                wifiLabel = "";
+            } else {
+                wifiLabel = context.getString(
+                        R.string.status_bar_settings_signal_meter_disconnected);
+            }
+        }
+
+        if (mBluetoothTethered) {
+            combinedLabel = mContext.getString(R.string.bluetooth_tethered);
+            mMSimcombinedSignalIconId[phoneId] = mBluetoothTetherIconId;
+            mMSimContentDescriptionCombinedSignal[phoneId] = mContext.getString(
+                    R.string.accessibility_bluetooth_tether);
+        }
+
+        final boolean ethernetConnected = (mConnectedNetworkType ==
+                ConnectivityManager.TYPE_ETHERNET);
+        if (ethernetConnected) {
+            // TODO: icons and strings for Ethernet connectivity
+            combinedLabel = mConnectedNetworkTypeName;
+        }
+
+        if (mAirplaneMode &&
+                (mMSimServiceState[phoneId] == null || (!hasService(phoneId)
+                    && !mMSimServiceState[phoneId].isEmergencyOnly()))) {
+            // Only display the flight-mode icon if not in "emergency calls only" mode.
+
+            // look again; your radios are now airplanes
+            mMSimContentDescriptionPhoneSignal[phoneId] = mContext.getString(
+                    R.string.accessibility_airplane_mode);
+            mAirplaneIconId = R.drawable.stat_sys_signal_flightmode;
+            mMSimPhoneSignalIconId[phoneId] = mMSimDataSignalIconId[phoneId]
+                    = mMSimDataTypeIconId[phoneId] = 0;
+            if (phoneId == dataSub) {
+                mQSDataTypeIconId = 0;
+                mNetworkName = mNetworkNameDefault;
+            }
+
+            // combined values from connected wifi take precedence over airplane mode
+            if (mWifiConnected) {
+                // Suppress "No internet connection." from mobile if wifi connected.
+                mobileLabel = "";
+            } else {
+                if (mHasMobileDataFeature) {
+                    // let the mobile icon show "No internet connection."
+                    wifiLabel = "";
+                } else {
+                    wifiLabel = context.getString(
+                            R.string.status_bar_settings_signal_meter_disconnected);
+                    combinedLabel = wifiLabel;
+                }
+                mMSimContentDescriptionCombinedSignal[phoneId] =
+                        mContentDescriptionPhoneSignal;
+                mMSimcombinedSignalIconId[phoneId] = mMSimDataSignalIconId[phoneId];
+            }
+            mMSimDataTypeIconId[phoneId] = 0;
+            if (phoneId == dataSub) {
+                mQSDataTypeIconId = 0;
+            }
+
+            mMSimcombinedSignalIconId[phoneId] = mMSimDataSignalIconId[phoneId];
+        }
+        else if (!mMSimDataConnected[phoneId] && !mWifiConnected && !mBluetoothTethered &&
+                !mWimaxConnected && !ethernetConnected) {
+            // pretty much totally disconnected
+
+            combinedLabel = context.getString(
+                    R.string.status_bar_settings_signal_meter_disconnected);
+            // On devices without mobile radios, we want to show the wifi icon
+            mMSimcombinedSignalIconId[phoneId] =
+                    mHasMobileDataFeature ? mMSimDataSignalIconId[phoneId] : mWifiIconId;
+            mMSimContentDescriptionCombinedSignal[phoneId] = mHasMobileDataFeature
+                    ? mMSimContentDescriptionDataType[phoneId] : mContentDescriptionWifi;
+        }
+
+        if (!mMSimDataConnected[phoneId]) {
+            Slog.d(TAG, "refreshViews: Data not connected!! Set no data type icon / Roaming for"
+                    + " phoneId: " + phoneId);
+            mMSimDataTypeIconId[phoneId] = 0;
+            if (phoneId == dataSub) {
+                mQSDataTypeIconId = 0;
+            }
+            if (isCdma(phoneId)) {
+                if (isCdmaEri(phoneId)) {
+                    mMSimDataTypeIconId[phoneId] =
+                            R.drawable.stat_sys_data_fully_connected_roam;
+                    if (phoneId == dataSub) {
+                        mQSDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                    }
+                }
+            } else if (mPhone.isNetworkRoaming(phoneId)) {
+                mMSimDataTypeIconId[phoneId] = R.drawable.stat_sys_data_fully_connected_roam;
+                if (phoneId == dataSub) {
+                    mQSDataTypeIconId = R.drawable.stat_sys_data_fully_connected_roam;
+                }
+            }
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "refreshViews connected={"
+                    + (mWifiConnected?" wifi":"")
+                    + (mMSimDataConnected[phoneId]?" data":"")
+                    + " } level="
+                    + ((mMSimSignalStrength[phoneId] == null)?"??":Integer.toString
+                            (mMSimSignalStrength[phoneId].getLevel()))
+                    + " mMSimcombinedSignalIconId=0x"
+                    + Integer.toHexString(mMSimcombinedSignalIconId[phoneId])
+                    + "/" + getResourceName(mMSimcombinedSignalIconId[phoneId])
+                    + " mMSimcombinedActivityIconId=0x" + Integer.toHexString
+                            (mMSimcombinedActivityIconId[phoneId])
+                    + " mAirplaneMode=" + mAirplaneMode
+                    + " mMSimDataActivity=" + mMSimDataActivity[phoneId]
+                    + " mMSimPhoneSignalIconId=0x" + Integer.toHexString
+                            (mMSimPhoneSignalIconId[phoneId])
+                    + " mMSimDataDirectionIconId=0x" + Integer.toHexString
+                            (mMSimDataDirectionIconId[phoneId])
+                    + " mMSimDataSignalIconId=0x" + Integer.toHexString
+                            (mMSimDataSignalIconId[phoneId])
+                    + " mMSimDataTypeIconId=0x" + Integer.toHexString
+                            (mMSimDataTypeIconId[phoneId])
+                    + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
+                    + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
+        }
+
+        // update QS
+        for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
+            notifySignalsChangedCallbacks(cb);
+        }
+
+        if (mMSimLastPhoneSignalIconId[phoneId] != mMSimPhoneSignalIconId[phoneId]
+         || mLastWifiIconId                 != mWifiIconId
+         || mLastWimaxIconId                != mWimaxIconId
+         || mMSimLastDataTypeIconId[phoneId] != mMSimDataTypeIconId[phoneId]
+         || mLastAirplaneMode               != mAirplaneMode)
+        {
+            // NB: the mLast*s will be updated later
+            for (MSimSignalCluster cluster : mSimSignalClusters) {
+                refreshSignalCluster(cluster, phoneId);
+            }
+        }
+
+        if (mLastAirplaneMode != mAirplaneMode) {
+            mLastAirplaneMode = mAirplaneMode;
+        }
+
+        // the phone icon on phones
+        if (mMSimLastPhoneSignalIconId[phoneId] != mMSimPhoneSignalIconId[phoneId]) {
+            mMSimLastPhoneSignalIconId[phoneId] = mMSimPhoneSignalIconId[phoneId];
+        }
+
+        // the data icon on phones
+        if (mMSimLastDataDirectionIconId[phoneId] != mMSimDataDirectionIconId[phoneId]) {
+            mMSimLastDataDirectionIconId[phoneId] = mMSimDataDirectionIconId[phoneId];
+        }
+
+
+        // the wifi icon on phones
+        if (mLastWifiIconId != mWifiIconId) {
+            mLastWifiIconId = mWifiIconId;
+        }
+
+        // the wimax icon on phones
+        if (mLastWimaxIconId != mWimaxIconId) {
+            mLastWimaxIconId = mWimaxIconId;
+        }
+        // the combined data signal icon
+        if (mMSimLastCombinedSignalIconId[phoneId] !=
+                mMSimcombinedSignalIconId[phoneId]) {
+            mMSimLastCombinedSignalIconId[phoneId] = mMSimcombinedSignalIconId[phoneId];
+        }
+
+        // the data network type overlay
+        if (mMSimLastDataTypeIconId[phoneId] != mMSimDataTypeIconId[phoneId]) {
+            mMSimLastDataTypeIconId[phoneId] = mMSimDataTypeIconId[phoneId];
+        }
+
+      // the combinedLabel in the notification panel
+        if (!mLastCombinedLabel.equals(combinedLabel)) {
+            mLastCombinedLabel = combinedLabel;
+            N = mCombinedLabelViews.size();
+            for (int i=0; i<N; i++) {
+                TextView v = mCombinedLabelViews.get(i);
+                v.setText(combinedLabel);
+            }
+        }
+
+        // wifi label
+        N = mWifiLabelViews.size();
+        for (int i=0; i<N; i++) {
+            TextView v = mWifiLabelViews.get(i);
+            v.setText(wifiLabel);
+            if ("".equals(wifiLabel)) {
+                v.setVisibility(View.GONE);
+            } else {
+                v.setVisibility(View.VISIBLE);
+            }
+        }
+
+        // mobile label
+        setCarrierText();
+        N = mMobileLabelViews.size();
+        for (int i=0; i<N; i++) {
+            TextView v = mMobileLabelViews.get(i);
+            v.setText(mobileLabel);
+            if ("".equals(mobileLabel)) {
+                v.setVisibility(View.GONE);
+            } else {
+                v.setVisibility(View.VISIBLE);
+            }
+        }
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args, int phoneId) {
+        pw.println("NetworkController for SUB : " + phoneId + " state:");
+        pw.println(String.format("  %s network type %d (%s)",
+                mConnected?"CONNECTED":"DISCONNECTED",
+                mConnectedNetworkType, mConnectedNetworkTypeName));
+        pw.println("  - telephony ------");
+        pw.print("  hasService()=");
+        pw.println(hasService(phoneId));
+        pw.print("  mHspaDataDistinguishable=");
+        pw.println(mHspaDataDistinguishable);
+        pw.print("  mMSimDataConnected=");
+        pw.println(mMSimDataConnected[phoneId]);
+        pw.print("  mMSimState=");
+        pw.println(mMSimState[phoneId]);
+        pw.print("  mPhoneState=");
+        pw.println(mPhoneState);
+        pw.print("  mDataState=");
+        pw.println(mDataState);
+        pw.print("  mMSimDataActivity=");
+        pw.println(mMSimDataActivity[phoneId]);
+        pw.print("  mDataNetType=");
+        pw.print(mDataNetType);
+        pw.print("/");
+        pw.println(TelephonyManager.getNetworkTypeName(mDataNetType));
+        pw.print("  mMSimServiceState=");
+        pw.println(mMSimServiceState[phoneId]);
+        pw.print("  mMSimSignalStrength=");
+        pw.println(mMSimSignalStrength[phoneId]);
+        pw.print("  mLastSignalLevel");
+        pw.println(mLastSignalLevel);
+        pw.print("  mMSimNetworkName=");
+        pw.println(mMSimNetworkName[phoneId]);
+        pw.print("  mNetworkNameDefault=");
+        pw.println(mNetworkNameDefault);
+        pw.print("  mNetworkNameSeparator=");
+        pw.println(mNetworkNameSeparator.replace("\n","\\n"));
+        pw.print("  mMSimPhoneSignalIconId=0x");
+        pw.print(Integer.toHexString(mMSimPhoneSignalIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimPhoneSignalIconId[phoneId]));
+        pw.print("  mMSimDataDirectionIconId=");
+        pw.print(Integer.toHexString(mMSimDataDirectionIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimDataDirectionIconId[phoneId]));
+        pw.print("  mMSimDataSignalIconId=");
+        pw.print(Integer.toHexString(mMSimDataSignalIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimDataSignalIconId[phoneId]));
+        pw.print("  mMSimDataTypeIconId=");
+        pw.print(Integer.toHexString(mMSimDataTypeIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimDataTypeIconId[phoneId]));
+
+        pw.println("  - wifi ------");
+        pw.print("  mWifiEnabled=");
+        pw.println(mWifiEnabled);
+        pw.print("  mWifiConnected=");
+        pw.println(mWifiConnected);
+        pw.print("  mWifiRssi=");
+        pw.println(mWifiRssi);
+        pw.print("  mWifiLevel=");
+        pw.println(mWifiLevel);
+        pw.print("  mWifiSsid=");
+        pw.println(mWifiSsid);
+        pw.println(String.format("  mWifiIconId=0x%08x/%s",
+                    mWifiIconId, getResourceName(mWifiIconId)));
+        pw.print("  mWifiActivity=");
+        pw.println(mWifiActivity);
+
+        if (mWimaxSupported) {
+            pw.println("  - wimax ------");
+            pw.print("  mIsWimaxEnabled="); pw.println(mIsWimaxEnabled);
+            pw.print("  mWimaxConnected="); pw.println(mWimaxConnected);
+            pw.print("  mWimaxIdle="); pw.println(mWimaxIdle);
+            pw.println(String.format("  mWimaxIconId=0x%08x/%s",
+                        mWimaxIconId, getResourceName(mWimaxIconId)));
+            pw.println(String.format("  mWimaxSignal=%d", mWimaxSignal));
+            pw.println(String.format("  mWimaxState=%d", mWimaxState));
+            pw.println(String.format("  mWimaxExtraState=%d", mWimaxExtraState));
+        }
+
+        pw.println("  - Bluetooth ----");
+        pw.print("  mBtReverseTethered=");
+        pw.println(mBluetoothTethered);
+
+        pw.println("  - connectivity ------");
+        pw.print("  mInetCondition=");
+        pw.println(mInetCondition);
+
+        pw.println("  - icons ------");
+        pw.print("  mMSimLastPhoneSignalIconId=0x");
+        pw.print(Integer.toHexString(mMSimLastPhoneSignalIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimLastPhoneSignalIconId[phoneId]));
+        pw.print("  mMSimLastDataDirectionIconId=0x");
+        pw.print(Integer.toHexString(mMSimLastDataDirectionIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimLastDataDirectionIconId[phoneId]));
+        pw.print("  mLastWifiIconId=0x");
+        pw.print(Integer.toHexString(mLastWifiIconId));
+        pw.print("/");
+        pw.println(getResourceName(mLastWifiIconId));
+        pw.print("  mMSimLastCombinedSignalIconId=0x");
+        pw.print(Integer.toHexString(mMSimLastCombinedSignalIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimLastCombinedSignalIconId[phoneId]));
+        pw.print("  mMSimLastDataTypeIconId=0x");
+        pw.print(Integer.toHexString(mMSimLastDataTypeIconId[phoneId]));
+        pw.print("/");
+        pw.println(getResourceName(mMSimLastDataTypeIconId[phoneId]));
+        pw.print("  mMSimLastCombinedLabel=");
+        pw.print(mLastCombinedLabel);
+        pw.println("");
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 821da07..5573f79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -60,12 +60,12 @@
         implements NetworkController, DemoMode {
     // debug
     static final String TAG = "StatusBar.NetworkController";
-    static final boolean DEBUG = false;
+    static final boolean DEBUG = true;
     static final boolean CHATTY = false; // additional diagnostics, but not logspew
 
     // telephony
     boolean mHspaDataDistinguishable;
-    final TelephonyManager mPhone;
+    private TelephonyManager mPhone;
     boolean mDataConnected;
     IccCardConstants.State mSimState = IccCardConstants.State.READY;
     int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
@@ -85,6 +85,8 @@
     int mDataTypeIconId;
     int mQSDataTypeIconId;
     int mAirplaneIconId;
+    int mNoSimIconId;
+    int mLastSimIconId;
     boolean mDataActive;
     boolean mNoSim;
     int mLastSignalLevel;
@@ -99,8 +101,8 @@
     String mContentDescriptionDataType;
 
     // wifi
-    final WifiManager mWifiManager;
-    AsyncChannel mWifiChannel;
+    protected WifiManager mWifiManager;
+    protected AsyncChannel mWifiChannel;
     boolean mWifiEnabled, mWifiConnected;
     int mWifiRssi, mWifiLevel;
     String mWifiSsid;
@@ -109,39 +111,40 @@
     int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE;
 
     // bluetooth
-    private boolean mBluetoothTethered = false;
-    private int mBluetoothTetherIconId =
+    protected boolean mBluetoothTethered = false;
+    protected int mBluetoothTetherIconId =
         com.android.internal.R.drawable.stat_sys_tether_bluetooth;
 
     //wimax
-    private boolean mWimaxSupported = false;
-    private boolean mIsWimaxEnabled = false;
-    private boolean mWimaxConnected = false;
-    private boolean mWimaxIdle = false;
-    private int mWimaxIconId = 0;
-    private int mWimaxSignal = 0;
-    private int mWimaxState = 0;
-    private int mWimaxExtraState = 0;
+    protected boolean mWimaxSupported = false;
+    protected boolean mIsWimaxEnabled = false;
+    protected boolean mWimaxConnected = false;
+    protected boolean mWimaxIdle = false;
+    protected int mWimaxIconId = 0;
+    protected int mWimaxSignal = 0;
+    protected int mWimaxState = 0;
+    protected int mWimaxExtraState = 0;
+    protected int mDataServiceState = ServiceState.STATE_OUT_OF_SERVICE;
 
     // data connectivity (regardless of state, can we access the internet?)
     // state of inet connection - 0 not connected, 100 connected
-    private boolean mConnected = false;
-    private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
-    private String mConnectedNetworkTypeName;
-    private int mLastConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+    protected boolean mConnected = false;
+    protected int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+    protected String mConnectedNetworkTypeName;
+    protected int mLastConnectedNetworkType = ConnectivityManager.TYPE_NONE;
 
-    private int mInetCondition = 0;
-    private int mLastInetCondition = 0;
-    private static final int INET_CONDITION_THRESHOLD = 50;
+    protected int mInetCondition = 0;
+    protected int mLastInetCondition = 0;
+    protected static final int INET_CONDITION_THRESHOLD = 50;
 
-    private boolean mAirplaneMode = false;
-    private boolean mLastAirplaneMode = true;
+    protected boolean mAirplaneMode = false;
+    protected boolean mLastAirplaneMode = true;
 
     private Locale mLocale = null;
     private Locale mLastLocale = null;
 
     // our ui
-    Context mContext;
+    protected Context mContext;
     ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>();
     ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>();
     ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
@@ -157,7 +160,7 @@
     int mLastDataTypeIconId = -1;
     String mLastCombinedLabel = "";
 
-    private boolean mHasMobileDataFeature;
+    protected boolean mHasMobileDataFeature;
 
     boolean mDataAndWifiStacked = false;
 
@@ -193,13 +196,7 @@
         updateWimaxIcons();
 
         // telephony
-        mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
-        mPhone.listen(mPhoneStateListener,
-                          PhoneStateListener.LISTEN_SERVICE_STATE
-                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                        | PhoneStateListener.LISTEN_CALL_STATE
-                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+        registerPhoneStateListener(context);
         mHspaDataDistinguishable = mContext.getResources().getBoolean(
                 R.bool.config_hspa_data_distinguishable);
         mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator);
@@ -227,6 +224,9 @@
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+
+        filter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
+
         mWimaxSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_wimaxEnabled);
         if(mWimaxSupported) {
@@ -268,6 +268,28 @@
         return (mServiceState != null && mServiceState.isEmergencyOnly());
     }
 
+    protected void createWifiHandler() {
+        // wifi
+        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+        Handler handler = new WifiHandler();
+        mWifiChannel = new AsyncChannel();
+        Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
+        if (wifiMessenger != null) {
+            mWifiChannel.connect(mContext, handler, wifiMessenger);
+        }
+    }
+
+    protected void registerPhoneStateListener(Context context) {
+        // telephony
+        mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+        mPhone.listen(mPhoneStateListener,
+                          PhoneStateListener.LISTEN_SERVICE_STATE
+                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+                        | PhoneStateListener.LISTEN_CALL_STATE
+                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+    }
+
     public void addCombinedLabelView(TextView v) {
         mCombinedLabelViews.add(v);
     }
@@ -547,7 +569,7 @@
         }
     };
 
-    private final void updateSimState(Intent intent) {
+    protected void updateSimState(Intent intent) {
         String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
         if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
             mSimState = IccCardConstants.State.ABSENT;
@@ -602,7 +624,7 @@
         return retVal;
     }
 
-    private void updateAirplaneMode() {
+    protected void updateAirplaneMode() {
         mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
             Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
     }
@@ -782,7 +804,7 @@
                                 R.string.accessibility_data_connection_lte);
                     }
                     break;
-                default:
+                case TelephonyManager.NETWORK_TYPE_GPRS:
                     if (!mShowAtLeastThreeGees) {
                         mDataIconList = TelephonyIcons.DATA_G[inetCondition];
                         mDataTypeIconId = showDataTypeIcon ?
@@ -799,6 +821,13 @@
                                 R.string.accessibility_data_connection_3g);
                     }
                     break;
+                default:
+                    if (DEBUG) {
+                        Log.e(TAG, "updateDataNetType unknown radio:" + mDataNetType);
+                    }
+                    mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+                    mDataTypeIconId = 0;
+                    break;
             }
         }
 
@@ -944,7 +973,7 @@
         }
     }
 
-    private void updateWifiState(Intent intent) {
+    protected void updateWifiState(Intent intent) {
         final String action = intent.getAction();
         if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
             mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
@@ -979,7 +1008,7 @@
         updateWifiIcons();
     }
 
-    private void updateWifiIcons() {
+    protected void updateWifiIcons() {
         int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIFI);
         if (mWifiConnected) {
             mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
@@ -1015,7 +1044,7 @@
 
 
     // ===== Wimax ===================================================================
-    private final void updateWimaxState(Intent intent) {
+    protected final void updateWimaxState(Intent intent) {
         final String action = intent.getAction();
         boolean wasConnected = mWimaxConnected;
         if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
@@ -1039,7 +1068,7 @@
         updateWimaxIcons();
     }
 
-    private void updateWimaxIcons() {
+    protected void updateWimaxIcons() {
         if (mIsWimaxEnabled) {
             if (mWimaxConnected) {
                 int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
@@ -1060,7 +1089,7 @@
 
     // ===== Full or limited Internet connectivity ==================================
 
-    private void updateConnectivity(Intent intent) {
+    protected void updateConnectivity(Intent intent) {
         if (CHATTY) {
             Log.d(TAG, "updateConnectivity: intent=" + intent);
         }
@@ -1502,7 +1531,7 @@
         pw.println("");
     }
 
-    private String getResourceName(int resId) {
+    protected String getResourceName(int resId) {
         if (resId != 0) {
             final Resources res = mContext.getResources();
             try {