summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI')
-rw-r--r--packages/SystemUI/res/anim/recents_from_app_enter.xml2
-rw-r--r--packages/SystemUI/res/anim/recents_from_app_exit.xml2
-rw-r--r--packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml6
-rw-r--r--packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml5
-rw-r--r--packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml2
-rw-r--r--packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml7
-rw-r--r--packages/SystemUI/res/drawable-hdpi/btn_fab_recents.pngbin4248 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/btn_fab_recents.pngbin2715 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.pngbin5938 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.pngbin9255 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml8
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_recent_panel.xml2
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_bar.xml10
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/recents_task_view.xml8
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml1
-rw-r--r--packages/SystemUI/res/layout/status_bar_recent_panel.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml59
-rw-r--r--packages/SystemUI/res/values/dimens.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java223
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java)17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java)14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java2449
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java144
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java7
-rw-r--r--packages/SystemUI/tests/Android.mk12
-rw-r--r--packages/SystemUI/tests/AndroidManifest.xml2
l---------packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java15
73 files changed, 2285 insertions, 1671 deletions
diff --git a/packages/SystemUI/res/anim/recents_from_app_enter.xml b/packages/SystemUI/res/anim/recents_from_app_enter.xml
index 6abe8b3..10ddce6 100644
--- a/packages/SystemUI/res/anim/recents_from_app_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_app_enter.xml
@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
-
+<!-- Recents Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
diff --git a/packages/SystemUI/res/anim/recents_from_app_exit.xml b/packages/SystemUI/res/anim/recents_from_app_exit.xml
index 1447a5a..c98ecf4 100644
--- a/packages/SystemUI/res/anim/recents_from_app_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_app_exit.xml
@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
-
+<!-- Incoming Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="normal">
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
index 20e7764..7de4460 100644
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
@@ -16,13 +16,13 @@
** limitations under the License.
*/
-->
-
+<!-- Recents Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="normal">
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear"
- android:duration="50"/>
+ android:duration="1"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
index 92a8882..e0e2fc8 100644
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
@@ -16,14 +16,13 @@
** limitations under the License.
*/
-->
-
+<!-- Launcher Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:startOffset="50"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:duration="100"/>
+ android:duration="@integer/recents_enter_from_home_transition_duration"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
index 4e1d66d..ea82835 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
-
+<!-- Launcher Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="normal">
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
index d7a12a4..a8bdc8e 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
@@ -16,14 +16,13 @@
** limitations under the License.
*/
-->
-
+<!-- Recents Activity -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:startOffset="100"
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear"
- android:duration="50"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png
deleted file mode 100644
index b95fde5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png
deleted file mode 100644
index 6bbed06..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png
deleted file mode 100644
index 4cdd0aa..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png
deleted file mode 100644
index 2220d60..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml b/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
index 6424a65..8a8164a 100644
--- a/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
+++ b/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
@@ -16,5 +16,11 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ff9cdfd9">
- <item android:drawable="@drawable/btn_fab_recents" />
+ <item>
+ <shape android:shape="oval">
+ <solid android:color="#9cc8c4" />
+ <size android:width="@dimen/recents_lock_to_app_size"
+ android:height="@dimen/recents_lock_to_app_size" />
+ </shape>
+ </item>
</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 0c0be29..b5d2f86 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -20,7 +20,7 @@
<com.android.systemui.recent.RecentsPanelView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/recents_root"
android:layout_height="match_parent"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index c2733fb..456d2f9 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -19,7 +19,7 @@
<!-- navigation bar for sw600dp (small tablets) -->
<com.android.systemui.statusbar.phone.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@drawable/system_bar_background"
@@ -57,6 +57,7 @@
android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
+ android:scaleType="centerInside"
systemui:keyCode="4"
android:layout_weight="0"
android:contentDescription="@string/accessibility_back"
@@ -65,6 +66,7 @@
android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_home"
+ android:scaleType="centerInside"
systemui:keyCode="3"
systemui:keyRepeat="true"
android:layout_weight="0"
@@ -74,6 +76,7 @@
android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
+ android:scaleType="centerInside"
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
@@ -91,6 +94,7 @@
android:layout_width="@dimen/navigation_extra_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_menu"
+ android:scaleType="centerInside"
android:layout_marginEnd="2dp"
systemui:keyCode="82"
android:visibility="invisible"
@@ -198,6 +202,7 @@
android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
+ android:scaleType="centerInside"
systemui:keyCode="4"
android:layout_weight="0"
android:contentDescription="@string/accessibility_back"
@@ -206,6 +211,7 @@
android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_home"
+ android:scaleType="centerInside"
systemui:keyCode="3"
systemui:keyRepeat="true"
android:layout_weight="0"
@@ -215,6 +221,7 @@
android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
+ android:scaleType="centerInside"
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
@@ -233,6 +240,7 @@
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
android:src="@drawable/ic_sysbar_menu"
+ android:scaleType="centerInside"
systemui:keyCode="82"
android:visibility="invisible"
android:contentDescription="@string/accessibility_menu" />
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 9d7c5a0..898389d 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -20,7 +20,7 @@
<com.android.systemui.statusbar.phone.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="@drawable/system_bar_background"
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index f776a87..a996260 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:paddingLeft="16dp"
android:paddingRight="16dp"
style="@style/BrightnessDialogContainer">
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index d1d3828..9c6f67c 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -29,8 +29,8 @@
<include layout="@layout/recents_task_view_header" />
<FrameLayout
android:id="@+id/lock_to_app_fab"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="@dimen/recents_lock_to_app_size"
+ android:layout_height="@dimen/recents_lock_to_app_size"
android:layout_gravity="bottom|right"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
@@ -38,8 +38,8 @@
android:contentDescription="@string/recents_lock_to_app_button_label"
android:background="@drawable/recents_lock_to_task_button_bg">
<ImageView
- android:layout_width="24dp"
- android:layout_height="24dp"
+ android:layout_width="@dimen/recents_lock_to_app_icon_size"
+ android:layout_height="@dimen/recents_lock_to_app_icon_size"
android:layout_gravity="center"
android:src="@drawable/recents_lock_to_app_pin" />
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9912e89..2fb7cdb 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -18,7 +18,7 @@
<!-- Extends RelativeLayout -->
<com.android.systemui.statusbar.phone.StatusBarHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/header"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="@dimen/status_bar_header_height"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index ef85847..4526af5 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -32,6 +32,7 @@
/>
<LinearLayout
+ android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
diff --git a/packages/SystemUI/res/layout/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
index 2f3968d..588873a 100644
--- a/packages/SystemUI/res/layout/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
@@ -20,7 +20,7 @@
<com.android.systemui.recent.RecentsPanelView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/recents_root"
android:layout_height="match_parent"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 44e0fd1..1152eea 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -144,42 +144,61 @@
<!-- The duration in seconds to wait before the dismiss buttons are shown. -->
<integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
+
<!-- The min animation duration for animating views that are currently visible. -->
<integer name="recents_filter_animate_current_views_duration">250</integer>
+
<!-- The min animation duration for animating views that are newly visible. -->
<integer name="recents_filter_animate_new_views_duration">250</integer>
- <!-- The min animation duration for animating the task bar in. -->
- <integer name="recents_animate_task_bar_enter_duration">225</integer>
- <!-- The animation delay for animating the first task in. This should roughly be the animation
- duration of the transition in to recents. -->
- <integer name="recents_animate_task_bar_enter_delay">275</integer>
- <!-- The min animation duration for animating the task bar out. -->
- <integer name="recents_animate_task_exit_to_home_duration">225</integer>
- <!-- The min animation duration for animating the task bar out. -->
- <integer name="recents_animate_task_bar_exit_duration">125</integer>
- <!-- The animation delay for animating the first task in. This should roughly be the animation
- duration of the transition in to recents from home. -->
- <integer name="recents_animate_task_enter_from_home_delay">150</integer>
- <!-- The min animation duration for animating the task in when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_duration">250</integer>
- <!-- The animation stagger to apply to each task animation when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_stagger_delay">12</integer>
- <!-- The short duration when animating in/out the lock to app button. -->
- <integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
- <!-- The long duration when animating in/out the lock to app button. -->
- <integer name="recents_animate_lock_to_app_button_long_duration">300</integer>
+
+ <!-- The duration of the window transition when coming to Recents from an app.
+ In order to defer the in-app animations until after the transition is complete,
+ we also need to use this value as the starting delay when animating the first
+ task decorations in. -->
+ <integer name="recents_enter_from_app_transition_duration">325</integer>
+
+ <!-- The duration for animating the task decorations in after transitioning from an app. -->
+ <integer name="recents_task_enter_from_app_duration">200</integer>
+
+ <!-- The duration for animating the task decorations out before transitioning to an app. -->
+ <integer name="recents_task_exit_to_app_duration">125</integer>
+
+ <!-- The duration of the window transition when coming to Recents from the Launcher.
+ In order to defer the in-app animations until after the transition is complete,
+ we also need to use this value as the starting delay when animating the task views
+ in from the bottom of the screen. -->
+ <integer name="recents_enter_from_home_transition_duration">100</integer>
+
+ <!-- The duration for animating the task from the bottom of the screen when transitioning
+ from home. -->
+ <integer name="recents_task_enter_from_home_duration">225</integer>
+
+ <!-- The stagger for each task when animating the task from the bottom of the screen when
+ transitioning from home. -->
+ <integer name="recents_task_enter_from_home_stagger_delay">12</integer>
+
+ <!-- The duration of the animation of the tasks to the bottom of the screen when leaving
+ Recents to go back to the Launcher. -->
+ <integer name="recents_task_exit_to_home_duration">225</integer>
+
<!-- The min animation duration for animating the nav bar scrim in. -->
<integer name="recents_nav_bar_scrim_enter_duration">400</integer>
+
<!-- The animation duration for animating the removal of a task view. -->
<integer name="recents_animate_task_view_remove_duration">250</integer>
+
<!-- The animation duration for scrolling the stack to a particular item. -->
<integer name="recents_animate_task_stack_scroll_duration">225</integer>
+
<!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
<integer name="recents_max_task_stack_view_dim">96</integer>
+
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
+
<!-- Transposes the search bar layout in landscape. -->
<bool name="recents_has_transposed_search_bar">true</bool>
+
<!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
<bool name="recents_has_transposed_nav_bar">true</bool>
<!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3d9f723..1143553 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -226,9 +226,6 @@
<!-- The amount of highlight to make on each task view. -->
<dimen name="recents_task_view_highlight">1.5dp</dimen>
- <!-- The height of the lock-to-app button. -->
- <dimen name="recents_task_view_lock_to_app_button_height">48dp</dimen>
-
<!-- The amount to offset when animating into an affiliate group. -->
<dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
@@ -257,6 +254,12 @@
<!-- The min alpha to apply to a task affiliation group color. -->
<item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
+ <!-- The size of the lock-to-app button. -->
+ <dimen name="recents_lock_to_app_size">56dp</dimen>
+
+ <!-- The size of the lock-to-app button icon. -->
+ <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
+
<!-- Space reserved for the cards behind the top card in the top stack -->
<dimen name="top_stack_peek_amount">12dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
new file mode 100644
index 0000000..2ff8f8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ViewInvertHelper.java
@@ -0,0 +1,101 @@
+/*
+ * 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
+ */
+
+package com.android.systemui;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+/**
+ * Helper to invert the colors of views and fade between the states.
+ */
+public class ViewInvertHelper {
+
+ private final Paint mDarkPaint = new Paint();
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final View mTarget;
+ private final ColorMatrix mMatrix = new ColorMatrix();
+ private final ColorMatrix mGrayscaleMatrix = new ColorMatrix();
+ private final long mFadeDuration;
+
+ public ViewInvertHelper(View target, long fadeDuration) {
+ mTarget = target;
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(mTarget.getContext(),
+ android.R.interpolator.linear_out_slow_in);
+ mFadeDuration = fadeDuration;
+ }
+
+ public void fade(final boolean invert, long delay) {
+ float startIntensity = invert ? 0f : 1f;
+ float endIntensity = invert ? 1f : 0f;
+ ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateInvertPaint((Float) animation.getAnimatedValue());
+ mTarget.setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!invert) {
+ mTarget.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ }
+ });
+ animator.setDuration(mFadeDuration);
+ animator.setInterpolator(mLinearOutSlowInInterpolator);
+ animator.setStartDelay(delay);
+ animator.start();
+ }
+
+ public void update(boolean invert) {
+ if (invert) {
+ updateInvertPaint(1f);
+ mTarget.setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+ } else {
+ mTarget.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ }
+
+ public View getTarget() {
+ return mTarget;
+ }
+
+ private void updateInvertPaint(float intensity) {
+ float components = 1 - 2 * intensity;
+ final float[] invert = {
+ components, 0f, 0f, 0f, 255f * intensity,
+ 0f, components, 0f, 0f, 255f * intensity,
+ 0f, 0f, components, 0f, 255f * intensity,
+ 0f, 0f, 0f, 1f, 0f
+ };
+ mMatrix.set(invert);
+ mGrayscaleMatrix.setSaturation(1 - intensity);
+ mMatrix.preConcat(mGrayscaleMatrix);
+ mDarkPaint.setColorFilter(new ColorMatrixColorFilter(mMatrix));
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 0ab6626..4f812bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -26,24 +26,26 @@ import com.android.systemui.statusbar.policy.Listenable;
/** Helper for managing a secure setting. **/
public abstract class SecureSetting extends ContentObserver implements Listenable {
+ private static final int DEFAULT = 0;
+
private final Context mContext;
private final String mSettingName;
private boolean mListening;
private int mUserId;
+ private int mObservedValue = DEFAULT;
- protected abstract void handleValueChanged(int value);
+ protected abstract void handleValueChanged(int value, boolean observedChange);
public SecureSetting(Context context, Handler handler, String settingName) {
super(handler);
mContext = context;
mSettingName = settingName;
mUserId = ActivityManager.getCurrentUser();
- setListening(true);
}
public int getValue() {
- return Secure.getIntForUser(mContext.getContentResolver(), mSettingName, 0, mUserId);
+ return Secure.getIntForUser(mContext.getContentResolver(), mSettingName, DEFAULT, mUserId);
}
public void setValue(int value) {
@@ -52,18 +54,23 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl
@Override
public void setListening(boolean listening) {
+ if (listening == mListening) return;
mListening = listening;
if (listening) {
+ mObservedValue = getValue();
mContext.getContentResolver().registerContentObserver(
Secure.getUriFor(mSettingName), false, this, mUserId);
} else {
mContext.getContentResolver().unregisterContentObserver(this);
+ mObservedValue = DEFAULT;
}
}
@Override
public void onChange(boolean selfChange) {
- handleValueChanged(getValue());
+ final int value = getValue();
+ handleValueChanged(value, value != mObservedValue);
+ mObservedValue = value;
}
public void setUserId(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 4d77348..1bc1d77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -77,6 +77,10 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleSecondaryClick() {
+ if (!mState.value) {
+ mState.value = true;
+ mController.setBluetoothEnabled(true);
+ }
showDetail(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 178590b..80ddd4a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -29,7 +29,8 @@ import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataController;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
/** Quick settings tile: Cellular **/
@@ -38,11 +39,13 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
"com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
private final NetworkController mController;
+ private final MobileDataController mDataController;
private final CellularDetailAdapter mDetailAdapter;
public CellularTile(Host host) {
super(host);
mController = host.getNetworkController();
+ mDataController = mController.getMobileDataController();
mDetailAdapter = new CellularDetailAdapter();
}
@@ -72,7 +75,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
@Override
protected void handleClick() {
- if (mController.isMobileDataSupported()) {
+ if (mDataController.isMobileDataSupported()) {
showDetail(true);
} else {
mHost.startSettingsActivity(CELLULAR_SETTINGS);
@@ -199,7 +202,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
@Override
public Boolean getToggleState() {
- return mController.isMobileDataSupported() ? mController.isMobileDataEnabled() : null;
+ return mDataController.isMobileDataSupported()
+ ? mDataController.isMobileDataEnabled() : null;
}
@Override
@@ -209,7 +213,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
@Override
public void setToggleState(boolean state) {
- mController.setMobileDataEnabled(state);
+ mDataController.setMobileDataEnabled(state);
}
@Override
@@ -217,7 +221,7 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
? convertView
: LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
- final DataUsageInfo info = mController.getDataUsageInfo();
+ final DataUsageInfo info = mDataController.getDataUsageInfo();
if (info == null) return v;
v.bind(info);
return v;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index b565afa..5963a45 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -41,8 +41,10 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
mSetting = new SecureSetting(mContext, mHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
@Override
- protected void handleValueChanged(int value) {
- mUsageTracker.trackUsage();
+ protected void handleValueChanged(int value, boolean observedChange) {
+ if (value != 0 || observedChange) {
+ mUsageTracker.trackUsage();
+ }
if (mListening) {
handleRefreshState(value);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 7bdb58f..eb816b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.AttributeSet;
-import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -61,7 +60,7 @@ public class DataUsageDetailView extends LinearLayout {
R.dimen.qs_data_usage_text_size);
}
- public void bind(NetworkController.DataUsageInfo info) {
+ public void bind(NetworkController.MobileDataController.DataUsageInfo info) {
final Resources res = mContext.getResources();
final int titleId;
final long bytes;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 7aa884e..4fb1189 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -31,7 +31,8 @@ import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
/** Quick settings tile: Wifi **/
@@ -39,12 +40,14 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
private final NetworkController mController;
+ private final AccessPointController mWifiController;
private final WifiDetailAdapter mDetailAdapter;
private final QSTile.SignalState mStateBeforeClick = newTileState();
public WifiTile(Host host) {
super(host);
mController = host.getNetworkController();
+ mWifiController = mController.getAccessPointController();
mDetailAdapter = new WifiDetailAdapter();
}
@@ -62,10 +65,10 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
public void setListening(boolean listening) {
if (listening) {
mController.addNetworkSignalChangedCallback(mCallback);
- mController.addAccessPointCallback(mDetailAdapter);
+ mWifiController.addAccessPointCallback(mDetailAdapter);
} else {
mController.removeNetworkSignalChangedCallback(mCallback);
- mController.removeAccessPointCallback(mDetailAdapter);
+ mWifiController.removeAccessPointCallback(mDetailAdapter);
}
}
@@ -87,7 +90,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
@Override
protected void handleSecondaryClick() {
- if (!mController.canConfigWifi()) {
+ if (!mWifiController.canConfigWifi()) {
mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
return;
}
@@ -231,7 +234,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
};
private final class WifiDetailAdapter implements DetailAdapter,
- NetworkController.AccessPointCallback, QSDetailItems.Callback {
+ NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
private QSDetailItems mItems;
private AccessPoint[] mAccessPoints;
@@ -261,7 +264,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
public View createDetailView(Context context, View convertView, ViewGroup parent) {
if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
mAccessPoints = null;
- mController.scanForAccessPoints();
+ mWifiController.scanForAccessPoints();
fireScanStateChanged(true);
mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
mItems.setTagSuffix("Wifi");
@@ -287,7 +290,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
if (item == null || item.tag == null) return;
final AccessPoint ap = (AccessPoint) item.tag;
if (!ap.isConnected) {
- if (mController.connect(ap)) {
+ if (mWifiController.connect(ap)) {
mHost.collapsePanels();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index bb9a105..38ce467 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -32,6 +32,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -361,8 +362,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// If the user has toggled it too quickly, then just eat up the event here (it's better than
// showing a janky screenshot).
// NOTE: Ideally, the screenshot mechanism would take the window transform into account
- long currentTime = System.currentTimeMillis();
- if ((currentTime > mLastToggleTime) && (currentTime - mLastToggleTime) < sMinToggleDelay) {
+ if ((SystemClock.elapsedRealtime() - mLastToggleTime) < sMinToggleDelay) {
return;
}
@@ -377,7 +377,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- mLastToggleTime = System.currentTimeMillis();
+ mLastToggleTime = SystemClock.elapsedRealtime();
return;
} else {
// Otherwise, start the recents activity
@@ -559,7 +559,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME, stackVr);
}
}
- mLastToggleTime = System.currentTimeMillis();
+ mLastToggleTime = SystemClock.elapsedRealtime();
}
/** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d1eadd8..6dc2edb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Pair;
import android.view.KeyEvent;
@@ -431,8 +432,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Update if we are getting a configuration change
if (savedInstanceState != null) {
// Update RecentsConfiguration
- mConfig = RecentsConfiguration.reinitialize(this,
- RecentsTaskLoader.getInstance().getSystemServicesProxy());
mConfig.updateOnConfigurationChange();
// Trigger the enter animation
onEnterAnimationTriggered();
@@ -566,13 +565,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_TAB: {
- boolean hasRepKeyTimeElapsed = (System.currentTimeMillis() -
+ boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
// Focus the next task in the stack
final boolean backward = event.isShiftPressed();
mRecentsView.focusNextTask(!backward);
- mLastTabKeyEventTime = System.currentTimeMillis();
+ mLastTabKeyEventTime = SystemClock.elapsedRealtime();
}
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 43d9dc1..2b33d14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -86,11 +86,15 @@ public class RecentsConfiguration {
public float taskStackWidthPaddingPct;
public float taskStackOverscrollPct;
+ /** Transitions */
+ public int transitionEnterFromAppDelay;
+ public int transitionEnterFromHomeDelay;
+
/** Task view animation and styles */
- public int taskViewEnterFromHomeDelay;
+ public int taskViewEnterFromAppDuration;
public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeStaggerDelay;
- public int taskViewEnterFromHomeStaggerDuration;
+ public int taskViewExitToAppDuration;
public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
@@ -110,16 +114,8 @@ public class RecentsConfiguration {
/** Task bar size & animations */
public int taskBarHeight;
- public int taskBarEnterAnimDuration;
- public int taskBarEnterAnimDelay;
- public int taskBarExitAnimDuration;
public int taskBarDismissDozeDelaySeconds;
- /** Lock to app */
- public int taskViewLockToAppButtonHeight;
- public int taskViewLockToAppShortAnimDuration;
- public int taskViewLockToAppLongAnimDuration;
-
/** Nav bar scrim */
public int navBarScrimEnterDuration;
@@ -226,15 +222,23 @@ public class RecentsConfiguration {
taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
+ // Transition
+ transitionEnterFromAppDelay =
+ res.getInteger(R.integer.recents_enter_from_app_transition_duration);
+ transitionEnterFromHomeDelay =
+ res.getInteger(R.integer.recents_enter_from_home_transition_duration);
+
// Task view animation and styles
- taskViewEnterFromHomeDelay =
- res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+ taskViewEnterFromAppDuration =
+ res.getInteger(R.integer.recents_task_enter_from_app_duration);
taskViewEnterFromHomeDuration =
- res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+ res.getInteger(R.integer.recents_task_enter_from_home_duration);
taskViewEnterFromHomeStaggerDelay =
- res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
+ res.getInteger(R.integer.recents_task_enter_from_home_stagger_delay);
+ taskViewExitToAppDuration =
+ res.getInteger(R.integer.recents_task_exit_to_app_duration);
taskViewExitToHomeDuration =
- res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
+ res.getInteger(R.integer.recents_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_remove_duration);
taskViewRemoveAnimTranslationXPx =
@@ -265,23 +269,9 @@ public class RecentsConfiguration {
// Task bar size & animations
taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
- taskBarEnterAnimDuration =
- res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
- taskBarEnterAnimDelay =
- res.getInteger(R.integer.recents_animate_task_bar_enter_delay);
- taskBarExitAnimDuration =
- res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
taskBarDismissDozeDelaySeconds =
res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
- // Lock to app
- taskViewLockToAppButtonHeight =
- res.getDimensionPixelSize(R.dimen.recents_task_view_lock_to_app_button_height);
- taskViewLockToAppShortAnimDuration =
- res.getInteger(R.integer.recents_animate_lock_to_app_button_short_duration);
- taskViewLockToAppLongAnimDuration =
- res.getInteger(R.integer.recents_animate_lock_to_app_button_long_duration);
-
// Nav bar scrim
navBarScrimEnterDuration =
res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 67a36b9..ba2903a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -170,66 +170,66 @@ class TaskResourceLoader implements Runnable {
} else {
RecentsConfiguration config = RecentsConfiguration.getInstance();
SystemServicesProxy ssp = mSystemServicesProxy;
- // If we've stopped the loader, then fall thorugh to the above logic to wait on
+ // If we've stopped the loader, then fall through to the above logic to wait on
// the load thread
- if (ssp == null) continue;
-
- // Load the next item from the queue
- final Task t = mLoadQueue.nextTask();
- if (t != null) {
- Drawable cachedIcon = mApplicationIconCache.get(t.key);
- Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
-
- // Load the application icon if it is stale or we haven't cached one yet
- if (cachedIcon == null) {
- cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
- mContext.getResources());
-
+ if (ssp != null) {
+ // Load the next item from the queue
+ final Task t = mLoadQueue.nextTask();
+ if (t != null) {
+ Drawable cachedIcon = mApplicationIconCache.get(t.key);
+ Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
+
+ // Load the application icon if it is stale or we haven't cached one yet
if (cachedIcon == null) {
- ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
- t.key.userId);
- if (info != null) {
- if (DEBUG) Log.d(TAG, "Loading icon: " + t.key);
- cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+ cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
+ mContext.getResources());
+
+ if (cachedIcon == null) {
+ ActivityInfo info = ssp.getActivityInfo(
+ t.key.baseIntent.getComponent(), t.key.userId);
+ if (info != null) {
+ if (DEBUG) Log.d(TAG, "Loading icon: " + t.key);
+ cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+ }
}
- }
- if (cachedIcon == null) {
- cachedIcon = mDefaultApplicationIcon;
- }
+ if (cachedIcon == null) {
+ cachedIcon = mDefaultApplicationIcon;
+ }
- // At this point, even if we can't load the icon, we will set the default
- // icon.
- mApplicationIconCache.put(t.key, cachedIcon);
- }
- // Load the thumbnail if it is stale or we haven't cached one yet
- if (cachedThumbnail == null) {
- if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
- if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key);
- cachedThumbnail = ssp.getTaskThumbnail(t.key.id);
+ // At this point, even if we can't load the icon, we will set the
+ // default icon.
+ mApplicationIconCache.put(t.key, cachedIcon);
}
+ // Load the thumbnail if it is stale or we haven't cached one yet
if (cachedThumbnail == null) {
- cachedThumbnail = mDefaultThumbnail;
+ if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
+ if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key);
+ cachedThumbnail = ssp.getTaskThumbnail(t.key.id);
+ }
+ if (cachedThumbnail == null) {
+ cachedThumbnail = mDefaultThumbnail;
+ }
+ // When svelte, we trim the memory to just the visible thumbnails when
+ // leaving, so don't thrash the cache as the user scrolls (just load
+ // them from scratch each time)
+ if (config.svelteLevel < RecentsConfiguration.SVELTE_LIMIT_CACHE) {
+ mThumbnailCache.put(t.key, cachedThumbnail);
+ }
}
- // When svelte, we trim the memory to just the visible thumbnails when
- // leaving, so don't thrash the cache as the user scrolls (just load them
- // from scratch each time)
- if (config.svelteLevel < RecentsConfiguration.SVELTE_LIMIT_CACHE) {
- mThumbnailCache.put(t.key, cachedThumbnail);
+ if (!mCancelled) {
+ // Notify that the task data has changed
+ final Drawable newIcon = cachedIcon;
+ final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail
+ ? null : cachedThumbnail;
+ mMainThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ t.notifyTaskDataLoaded(newThumbnail, newIcon);
+ }
+ });
}
}
- if (!mCancelled) {
- // Notify that the task data has changed
- final Drawable newIcon = cachedIcon;
- final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail
- ? null : cachedThumbnail;
- mMainThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- t.notifyTaskDataLoaded(newThumbnail, newIcon);
- }
- });
- }
}
// If there are no other items in the list, then just wait until something is added
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 5f8f3f2..fb05c01 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.views;
-import android.animation.ObjectAnimator;
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
@@ -35,8 +34,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
float mAlpha = 1f;
final float mMinAlpha = 0.25f;
- ObjectAnimator mClipBottomAnimator;
-
public AnimateableViewBounds(TaskView source, int cornerRadius) {
mConfig = RecentsConfiguration.getInstance();
mSourceView = source;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 162897e..1086160 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -64,7 +64,9 @@ public class SystemBarScrimViews {
mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
mStatusBarScrimView.animate()
.translationY(0)
- .setStartDelay(mConfig.taskBarEnterAnimDelay)
+ .setStartDelay(mConfig.launchedFromHome ?
+ mConfig.transitionEnterFromHomeDelay :
+ mConfig.transitionEnterFromAppDelay)
.setDuration(mConfig.navBarScrimEnterDuration)
.setInterpolator(mConfig.quintOutInterpolator)
.withStartAction(new Runnable() {
@@ -79,7 +81,9 @@ public class SystemBarScrimViews {
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
mNavBarScrimView.animate()
.translationY(0)
- .setStartDelay(mConfig.taskBarEnterAnimDelay)
+ .setStartDelay(mConfig.launchedFromHome ?
+ mConfig.transitionEnterFromHomeDelay :
+ mConfig.transitionEnterFromAppDelay)
.setDuration(mConfig.navBarScrimEnterDuration)
.setInterpolator(mConfig.quintOutInterpolator)
.withStartAction(new Runnable() {
@@ -101,7 +105,7 @@ public class SystemBarScrimViews {
mStatusBarScrimView.animate()
.translationY(-mStatusBarScrimView.getMeasuredHeight())
.setStartDelay(0)
- .setDuration(mConfig.taskBarExitAnimDuration)
+ .setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.start();
}
@@ -109,7 +113,7 @@ public class SystemBarScrimViews {
mNavBarScrimView.animate()
.translationY(mNavBarScrimView.getMeasuredHeight())
.setStartDelay(0)
- .setDuration(mConfig.taskBarExitAnimDuration)
+ .setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 1731d38..5732879 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -186,6 +186,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mUIDozeTrigger.stopDozing();
mUIDozeTrigger.resetTrigger();
}
+ mStackScroller.reset();
}
/** Requests that the views be synchronized with the model */
@@ -659,9 +660,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// If this is the first layout, then scroll to the front of the stack and synchronize the
// stack views immediately to load all the views
if (mAwaitingFirstLayout) {
- mStackScroller.setStackScrollToInitialState();
- requestSynchronizeStackViewsWithModel();
- synchronizeStackViewsWithModel();
+ if (mStackScroller.setStackScrollToInitialState()) {
+ requestSynchronizeStackViewsWithModel();
+ synchronizeStackViewsWithModel();
+ }
}
// Measure each of the TaskViews
@@ -915,7 +917,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView frontTv = getChildViewForTask(newFrontMostTask);
if (frontTv != null) {
frontTv.onTaskBound(newFrontMostTask);
- frontTv.fadeInActionButton(false);
+ frontTv.fadeInActionButton(0, mConfig.taskViewEnterFromAppDuration);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 04f7c6f..f7067be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -48,6 +48,11 @@ public class TaskStackViewScroller {
setStackScroll(getStackScroll());
}
+ /** Resets the task scroller. */
+ void reset() {
+ mStackScrollP = 0f;
+ }
+
/** Sets the callbacks */
void setCallbacks(TaskStackViewScrollerCallbacks cb) {
mCb = cb;
@@ -71,9 +76,14 @@ public class TaskStackViewScroller {
mStackScrollP = s;
}
- /** Sets the current stack scroll to the initial state when you first enter recents */
- public void setStackScrollToInitialState() {
+ /**
+ * Sets the current stack scroll to the initial state when you first enter recents.
+ * @return whether the stack progress changed.
+ */
+ public boolean setStackScrollToInitialState() {
+ float prevStackScrollP = mStackScrollP;
setStackScroll(getBoundedStackScroll(mLayoutAlgorithm.mInitialScrollP));
+ return Float.compare(prevStackScrollP, mStackScrollP) != 0;
}
/** Bounds the current scroll if necessary */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 27d2fda..d42fa15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -24,7 +24,6 @@ import android.graphics.*;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
-import android.view.ViewPropertyAnimator;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -271,24 +270,25 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
// Animate the thumbnail alpha before the dim animation (to prevent updating the
// hardware layer)
- mThumbnailView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+ mThumbnailView.startEnterRecentsAnimation(mConfig.transitionEnterFromAppDelay,
new Runnable() {
@Override
public void run() {
- animateDimToProgress(0, mConfig.taskBarEnterAnimDuration,
+ animateDimToProgress(0, mConfig.taskViewEnterFromAppDuration,
ctx.postAnimationTrigger.decrementOnAnimationEnd());
}
});
} else {
// Immediately start the dim animation
- animateDimToProgress(mConfig.taskBarEnterAnimDelay,
- mConfig.taskBarEnterAnimDuration,
+ animateDimToProgress(mConfig.transitionEnterFromAppDelay,
+ mConfig.taskViewEnterFromAppDuration,
ctx.postAnimationTrigger.decrementOnAnimationEnd());
}
ctx.postAnimationTrigger.increment();
// Animate the action button in
- fadeInActionButton(true);
+ fadeInActionButton(mConfig.transitionEnterFromAppDelay,
+ mConfig.taskViewEnterFromAppDuration);
} else {
// Animate the task up if it was occluding the launch target
if (ctx.currentTaskOccludesLaunchTarget) {
@@ -296,7 +296,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
setAlpha(0f);
animate().alpha(1f)
.translationY(transform.translationY)
- .setStartDelay(mConfig.taskBarEnterAnimDelay)
+ .setStartDelay(mConfig.transitionEnterFromAppDelay)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewEnterFromHomeDuration)
@@ -311,12 +311,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
ctx.postAnimationTrigger.increment();
}
}
- startDelay = mConfig.taskBarEnterAnimDelay;
+ startDelay = mConfig.transitionEnterFromAppDelay;
} else if (mConfig.launchedFromHome) {
// Animate the tasks up
int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
- int delay = mConfig.taskViewEnterFromHomeDelay +
+ int delay = mConfig.transitionEnterFromHomeDelay +
frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
setScaleX(transform.scale);
@@ -353,19 +353,17 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}, (startDelay / 2));
}
- public void fadeInActionButton(boolean withDelay) {
+ public void fadeInActionButton(int delay, int duration) {
// Hide the action button
mActionButtonView.setAlpha(0f);
// Animate the action button in
- ViewPropertyAnimator animator = mActionButtonView.animate().alpha(1f)
- .setDuration(mConfig.taskBarEnterAnimDuration)
+ mActionButtonView.animate().alpha(1f)
+ .setStartDelay(delay)
+ .setDuration(duration)
.setInterpolator(PhoneStatusBar.ALPHA_IN)
- .withLayer();
- if (withDelay) {
- animator.setStartDelay(mConfig.taskBarEnterAnimDelay);
- }
- animator.start();
+ .withLayer()
+ .start();
}
/** Animates this task view as it leaves recents by pressing home. */
@@ -391,7 +389,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Animate the dim
if (mDimAlpha > 0) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
- anim.setDuration(mConfig.taskBarExitAnimDuration);
+ anim.setDuration(mConfig.taskViewExitToAppDuration);
anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
anim.start();
}
@@ -406,7 +404,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mActionButtonView.animate()
.alpha(0f)
.setStartDelay(0)
- .setDuration(mConfig.taskBarExitAnimDuration)
+ .setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.withLayer()
.start();
@@ -421,7 +419,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.setStartDelay(0)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
- .setDuration(mConfig.taskBarExitAnimDuration)
+ .setDuration(mConfig.taskViewExitToAppDuration)
.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 5de84bd..1e5d9fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -235,7 +235,7 @@ public class TaskViewHeader extends FrameLayout {
.alpha(0f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
- .setDuration(mConfig.taskBarExitAnimDuration)
+ .setDuration(mConfig.taskViewExitToAppDuration)
.withLayer()
.start();
}
@@ -249,7 +249,7 @@ public class TaskViewHeader extends FrameLayout {
.alpha(1f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
- .setDuration(mConfig.taskBarEnterAnimDuration)
+ .setDuration(mConfig.taskViewEnterFromAppDuration)
.withLayer()
.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index c83248e..117a7d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -237,12 +237,12 @@ public class TaskViewThumbnail extends View {
/** Animates this task thumbnail as it enters Recents. */
void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
- mConfig.taskBarEnterAnimDuration, postAnimRunnable);
+ mConfig.taskViewEnterFromAppDuration, postAnimRunnable);
}
/** Animates this task thumbnail as it exits Recents. */
void startLaunchTaskAnimation(Runnable postAnimRunnable) {
- startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
+ startFadeAnimation(1f, 0, mConfig.taskViewExitToAppDuration, postAnimRunnable);
}
/** Starts a new thumbnail alpha animation. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 02b9378..7b60307 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -43,6 +43,7 @@ import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
/**
* Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -53,6 +54,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private static final long DOUBLETAP_TIMEOUT_MS = 1200;
private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
private static final int ACTIVATE_ANIMATION_LENGTH = 220;
+ private static final int DARK_ANIMATION_LENGTH = 170;
/**
* The amount of width, which is kept in the end when performing a disappear animation (also
@@ -84,6 +86,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
*/
private static final float VERTICAL_ANIMATION_START = 1.0f;
+ /**
+ * Scale for the background to animate from when exiting dark mode.
+ */
+ private static final float DARK_EXIT_SCALE_START = 0.93f;
+
private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR
= new PathInterpolator(0.6f, 0, 0.5f, 1);
private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
@@ -94,7 +101,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mDimmed;
private boolean mDark;
- private final Paint mDarkPaint = createDarkPaint();
private int mBgTint = 0;
private final int mRoundedRectCornerRadius;
@@ -332,40 +338,32 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
if (mDimmed != dimmed) {
mDimmed = dimmed;
if (fade) {
- fadeBackground();
+ fadeDimmedBackground();
} else {
updateBackground();
}
}
}
- public void setDark(boolean dark, boolean fade) {
- // TODO implement fade
- if (mDark != dark) {
- mDark = dark;
- if (mDark) {
- setLayerType(View.LAYER_TYPE_HARDWARE, mDarkPaint);
+ public void setDark(boolean dark, boolean fade, long delay) {
+ super.setDark(dark, fade, delay);
+ if (mDark == dark) {
+ return;
+ }
+ mDark = dark;
+ if (!dark && fade) {
+ if (mActivated) {
+ mBackgroundDimmed.setVisibility(View.VISIBLE);
+ mBackgroundNormal.setVisibility(View.VISIBLE);
} else {
- setLayerType(View.LAYER_TYPE_NONE, null);
+ mBackgroundDimmed.setVisibility(View.VISIBLE);
+ mBackgroundNormal.setVisibility(View.INVISIBLE);
}
+ fadeDarkToDimmed(delay);
+ } else {
+ updateBackground();
}
- }
-
- private static Paint createDarkPaint() {
- final Paint p = new Paint();
- final float[] invert = {
- -1f, 0f, 0f, 1f, 1f,
- 0f, -1f, 0f, 1f, 1f,
- 0f, 0f, -1f, 1f, 1f,
- 0f, 0f, 0f, 1f, 0f
- };
- final ColorMatrix m = new ColorMatrix(invert);
- final ColorMatrix grayscale = new ColorMatrix();
- grayscale.setSaturation(0);
- m.preConcat(grayscale);
- p.setColorFilter(new ColorMatrixColorFilter(m));
- return p;
- }
+ }
public void setShowingLegacyBackground(boolean showing) {
mShowingLegacyBackground = showing;
@@ -402,7 +400,39 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mBackgroundNormal.setRippleColor(rippleColor);
}
- private void fadeBackground() {
+ /**
+ * Fades the dimmed background when exiting dark mode.
+ */
+ private void fadeDarkToDimmed(long delay) {
+ mBackgroundDimmed.setAlpha(0f);
+ mBackgroundDimmed.setPivotX(mBackgroundDimmed.getWidth() / 2f);
+ mBackgroundDimmed.setPivotY(getActualHeight() / 2f);
+ mBackgroundDimmed.setScaleX(DARK_EXIT_SCALE_START);
+ mBackgroundDimmed.setScaleY(DARK_EXIT_SCALE_START);
+ mBackgroundDimmed.animate()
+ .alpha(1f)
+ .scaleX(1f)
+ .scaleY(1f)
+ .setDuration(DARK_ANIMATION_LENGTH)
+ .setStartDelay(delay)
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ // Jump state if we are cancelled
+ mBackgroundDimmed.setScaleX(1f);
+ mBackgroundDimmed.setScaleY(1f);
+ mBackgroundDimmed.setAlpha(1f);
+ }
+ })
+ .start();
+ }
+
+ /**
+ * Fades the background when the dimmed state changes.
+ */
+ private void fadeDimmedBackground() {
+ mBackgroundDimmed.animate().cancel();
mBackgroundNormal.animate().cancel();
if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
@@ -443,11 +473,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
}
private void updateBackground() {
- if (mDimmed) {
+ cancelFadeAnimations();
+ if (mDark) {
+ mBackgroundDimmed.setVisibility(View.INVISIBLE);
+ mBackgroundNormal.setVisibility(View.INVISIBLE);
+ } else if (mDimmed) {
mBackgroundDimmed.setVisibility(View.VISIBLE);
mBackgroundNormal.setVisibility(View.INVISIBLE);
} else {
- cancelFadeAnimations();
mBackgroundDimmed.setVisibility(View.INVISIBLE);
mBackgroundNormal.setVisibility(View.VISIBLE);
mBackgroundNormal.setAlpha(1f);
@@ -459,6 +492,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
if (mBackgroundAnimator != null) {
mBackgroundAnimator.cancel();
}
+ mBackgroundDimmed.animate().cancel();
mBackgroundNormal.animate().cancel();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 7345440..8ad8406 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -207,11 +207,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
@Override
- public void setDark(boolean dark, boolean fade) {
- super.setDark(dark, fade);
+ public void setDark(boolean dark, boolean fade, long delay) {
+ super.setDark(dark, fade, delay);
final NotificationContentView showing = getShowingLayout();
if (showing != null) {
- showing.setDark(dark, fade);
+ showing.setDark(dark, fade, delay);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index bf1e78e..ebc663c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -39,6 +39,7 @@ public abstract class ExpandableView extends FrameLayout {
private int mActualHeight;
protected int mClipTopAmount;
private boolean mActualHeightInitialized;
+ private boolean mDark;
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
public ExpandableView(Context context, AttributeSet attrs) {
@@ -185,8 +186,14 @@ public abstract class ExpandableView extends FrameLayout {
*
* @param dark Whether the notification should be dark.
* @param fade Whether an animation should be played to change the state.
+ * @param delay If fading, the delay of the animation.
*/
- public void setDark(boolean dark, boolean fade) {
+ public void setDark(boolean dark, boolean fade, long delay) {
+ mDark = dark;
+ }
+
+ public boolean isDark() {
+ return mDark;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 99214a0..27da6fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -42,14 +42,14 @@ import com.android.systemui.R;
public class NotificationContentView extends FrameLayout {
private static final long ANIMATION_DURATION_LENGTH = 170;
- private static final Paint INVERT_PAINT = createInvertPaint();
- private static final ColorFilter NO_COLOR_FILTER = new ColorFilter();
private final Rect mClipBounds = new Rect();
private View mContractedChild;
private View mExpandedChild;
+ private NotificationViewWrapper mContractedWrapper;
+
private int mSmallHeight;
private int mClipTopAmount;
private int mActualHeight;
@@ -84,8 +84,8 @@ public class NotificationContentView extends FrameLayout {
}
@Override
- protected void onFinishInflate() {
- super.onFinishInflate();
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
updateVisibility();
}
@@ -122,6 +122,7 @@ public class NotificationContentView extends FrameLayout {
sanitizeContractedLayoutParams(child);
addView(child);
mContractedChild = child;
+ mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child);
selectLayout(false /* animate */, true /* force */);
}
@@ -249,38 +250,10 @@ public class NotificationContentView extends FrameLayout {
return mExpandedChild != null;
}
- public void setDark(boolean dark, boolean fade) {
+ public void setDark(boolean dark, boolean fade, long delay) {
if (mDark == dark || mContractedChild == null) return;
mDark = dark;
- setImageViewDark(dark, fade, com.android.internal.R.id.right_icon);
- setImageViewDark(dark, fade, com.android.internal.R.id.icon);
- }
-
- private void setImageViewDark(boolean dark, boolean fade, int imageViewId) {
- // TODO: implement fade
- final ImageView v = (ImageView) mContractedChild.findViewById(imageViewId);
- if (v == null) return;
- final Drawable d = v.getBackground();
- if (dark) {
- v.setLayerType(LAYER_TYPE_HARDWARE, INVERT_PAINT);
- if (d != null) {
- v.setTag(R.id.doze_saved_filter_tag, d.getColorFilter() != null ? d.getColorFilter()
- : NO_COLOR_FILTER);
- d.setColorFilter(getResources().getColor(R.color.doze_small_icon_background_color),
- PorterDuff.Mode.SRC_ATOP);
- v.setImageAlpha(getResources().getInteger(R.integer.doze_small_icon_alpha));
- }
- } else {
- v.setLayerType(LAYER_TYPE_NONE, null);
- if (d != null) {
- final ColorFilter filter = (ColorFilter) v.getTag(R.id.doze_saved_filter_tag);
- if (filter != null) {
- d.setColorFilter(filter == NO_COLOR_FILTER ? null : filter);
- v.setTag(R.id.doze_saved_filter_tag, null);
- }
- v.setImageAlpha(0xff);
- }
- }
+ mContractedWrapper.setDark(dark, fade, delay);
}
@Override
@@ -290,16 +263,4 @@ public class NotificationContentView extends FrameLayout {
// layout, and saves us some layers.
return false;
}
-
- private static Paint createInvertPaint() {
- final Paint p = new Paint();
- final float[] invert = {
- -1f, 0f, 0f, 1f, 1f,
- 0f, -1f, 0f, 1f, 1f,
- 0f, 0f, -1f, 1f, 1f,
- 0f, 0f, 0f, 1f, 0f
- };
- p.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(invert)));
- return p;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java
new file mode 100644
index 0000000..045be3e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java
@@ -0,0 +1,48 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.statusbar;
+
+import android.view.View;
+
+import com.android.systemui.ViewInvertHelper;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+/**
+ * Wraps a notification containing a custom view.
+ */
+public class NotificationCustomViewWrapper extends NotificationViewWrapper {
+
+ private final ViewInvertHelper mInvertHelper;
+ private boolean mDark;
+
+ protected NotificationCustomViewWrapper(View view) {
+ super(view);
+ mInvertHelper = new ViewInvertHelper(view, NotificationPanelView.DOZE_ANIMATION_DURATION);
+ }
+
+ @Override
+ public void setDark(boolean dark, boolean fade, long delay) {
+ if (mDark != dark) {
+ mDark = dark;
+ if (fade) {
+ mInvertHelper.fade(dark, delay);
+ } else {
+ mInvertHelper.update(dark);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java
new file mode 100644
index 0000000..8f63a79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java
@@ -0,0 +1,42 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.View;
+
+/**
+ * Wraps a media notification.
+ */
+public class NotificationMediaViewWrapper extends NotificationTemplateViewWrapper {
+
+ private boolean mDark;
+
+ protected NotificationMediaViewWrapper(Context ctx, View view) {
+ super(ctx, view);
+ }
+
+ @Override
+ public void setDark(boolean dark, boolean fade, long delay) {
+ if (mDark != dark) {
+ mDark = dark;
+
+ // Only update the large icon, because the rest is already inverted.
+ setPictureGrayscale(dark, fade, delay);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
index edfd205..bfa3aa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -21,6 +21,8 @@ import android.util.AttributeSet;
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.ViewInvertHelper;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
/**
* Container view for overflowing notification icons on Keyguard.
@@ -28,6 +30,8 @@ import com.android.systemui.R;
public class NotificationOverflowContainer extends ActivatableNotificationView {
private NotificationOverflowIconsView mIconsView;
+ private ViewInvertHelper mViewInvertHelper;
+ private boolean mDark;
public NotificationOverflowContainer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -39,6 +43,20 @@ public class NotificationOverflowContainer extends ActivatableNotificationView {
mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
mIconsView.setOverflowIndicator(findViewById(R.id.more_icon_overflow));
+ mViewInvertHelper = new ViewInvertHelper(findViewById(R.id.content),
+ NotificationPanelView.DOZE_ANIMATION_DURATION);
+ }
+
+ @Override
+ public void setDark(boolean dark, boolean fade, long delay) {
+ super.setDark(dark, fade, delay);
+ if (mDark == dark) return;
+ mDark = dark;
+ if (fade) {
+ mViewInvertHelper.fade(dark, delay);
+ } else {
+ mViewInvertHelper.update(dark);
+ }
}
public NotificationOverflowIconsView getIconsView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
new file mode 100644
index 0000000..8dc14b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java
@@ -0,0 +1,223 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.statusbar;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.ViewInvertHelper;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
+
+/**
+ * Wraps a notification view inflated from a template.
+ */
+public class NotificationTemplateViewWrapper extends NotificationViewWrapper {
+
+ private final ViewInvertHelper mInvertHelper;
+ private final ImageView mIcon;
+ protected final ImageView mPicture;
+ private final ColorMatrix mGrayscaleColorMatrix = new ColorMatrix();
+ private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
+ 0, PorterDuff.Mode.SRC_ATOP);
+ private final int mIconDarkAlpha;
+ private final int mIconBackgroundColor;
+ private final int mIconBackgroundDarkColor;
+ private final Interpolator mLinearOutSlowInInterpolator;
+
+ private boolean mDark;
+
+ protected NotificationTemplateViewWrapper(Context ctx, View view) {
+ super(view);
+ mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
+ mIconBackgroundDarkColor =
+ ctx.getResources().getColor(R.color.doze_small_icon_background_color);
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(ctx,
+ android.R.interpolator.linear_out_slow_in);
+ View mainColumn = view.findViewById(com.android.internal.R.id.notification_main_column);
+ mInvertHelper = mainColumn != null
+ ? new ViewInvertHelper(mainColumn, NotificationPanelView.DOZE_ANIMATION_DURATION)
+ : null;
+ ImageView largeIcon = (ImageView) view.findViewById(com.android.internal.R.id.icon);
+ ImageView rightIcon = (ImageView) view.findViewById(com.android.internal.R.id.right_icon);
+ mIcon = resolveIcon(largeIcon, rightIcon);
+ mPicture = resolvePicture(largeIcon);
+ mIconBackgroundColor = resolveBackgroundColor(mIcon);
+ }
+
+ private ImageView resolveIcon(ImageView largeIcon, ImageView rightIcon) {
+ return largeIcon != null && largeIcon.getBackground() != null ? largeIcon
+ : rightIcon != null && rightIcon.getBackground() != null ? rightIcon
+ : null;
+ }
+
+ private ImageView resolvePicture(ImageView largeIcon) {
+ return largeIcon != null && largeIcon.getBackground() == null
+ ? largeIcon
+ : null;
+ }
+
+ private int resolveBackgroundColor(ImageView icon) {
+ if (icon != null && icon.getBackground() != null) {
+ ColorFilter filter = icon.getBackground().getColorFilter();
+ if (filter instanceof PorterDuffColorFilter) {
+ return ((PorterDuffColorFilter) filter).getColor();
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public void setDark(boolean dark, boolean fade, long delay) {
+ if (mDark != dark) {
+ mDark = dark;
+ if (mInvertHelper != null) {
+ if (fade) {
+ mInvertHelper.fade(dark, delay);
+ } else {
+ mInvertHelper.update(dark);
+ }
+ }
+ if (mIcon != null) {
+ if (fade) {
+ fadeIconColorFilter(mIcon, dark, delay);
+ fadeIconAlpha(mIcon, dark, delay);
+ } else {
+ updateIconColorFilter(mIcon, dark);
+ updateIconAlpha(mIcon, dark);
+ }
+ }
+ setPictureGrayscale(dark, fade, delay);
+ }
+ }
+
+ protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) {
+ if (mPicture != null) {
+ if (fade) {
+ fadeGrayscale(mPicture, grayscale, delay);
+ } else {
+ updateGrayscale(mPicture, grayscale);
+ }
+ }
+ }
+
+ private void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
+ boolean dark, long delay, Animator.AnimatorListener listener) {
+ float startIntensity = dark ? 0f : 1f;
+ float endIntensity = dark ? 1f : 0f;
+ ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
+ animator.addUpdateListener(updateListener);
+ animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+ animator.setInterpolator(mLinearOutSlowInInterpolator);
+ animator.setStartDelay(delay);
+ if (listener != null) {
+ animator.addListener(listener);
+ }
+ animator.start();
+ }
+
+ private void fadeIconColorFilter(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateIconColorFilter(target, (Float) animation.getAnimatedValue());
+ }
+ }, dark, delay, null /* listener */);
+ }
+
+ private void fadeIconAlpha(final ImageView target, boolean dark, long delay) {
+ startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float t = (float) animation.getAnimatedValue();
+ target.setImageAlpha((int) (255 * (1f - t) + mIconDarkAlpha * t));
+ }
+ }, dark, delay, null /* listener */);
+ }
+
+ protected void fadeGrayscale(final ImageView target, final boolean dark, long delay) {
+ startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ updateGrayscaleMatrix((float) animation.getAnimatedValue());
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ }
+ }, dark, delay, new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!dark) {
+ target.setColorFilter(null);
+ }
+ }
+ });
+ }
+
+ private void updateIconColorFilter(ImageView target, boolean dark) {
+ updateIconColorFilter(target, dark ? 1f : 0f);
+ }
+
+ private void updateIconColorFilter(ImageView target, float intensity) {
+ int color = interpolateColor(mIconBackgroundColor, mIconBackgroundDarkColor, intensity);
+ mIconColorFilter.setColor(color);
+ target.getBackground().mutate().setColorFilter(mIconColorFilter);
+ }
+
+ private void updateIconAlpha(ImageView target, boolean dark) {
+ target.setImageAlpha(dark ? mIconDarkAlpha : 255);
+ }
+
+ protected void updateGrayscale(ImageView target, boolean dark) {
+ if (dark) {
+ updateGrayscaleMatrix(1f);
+ target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+ } else {
+ target.setColorFilter(null);
+ }
+ }
+
+ private void updateGrayscaleMatrix(float intensity) {
+ mGrayscaleColorMatrix.setSaturation(1 - intensity);
+ }
+
+ private static int interpolateColor(int source, int target, float t) {
+ int aSource = Color.alpha(source);
+ int rSource = Color.red(source);
+ int gSource = Color.green(source);
+ int bSource = Color.blue(source);
+ int aTarget = Color.alpha(target);
+ int rTarget = Color.red(target);
+ int gTarget = Color.green(target);
+ int bTarget = Color.blue(target);
+ return Color.argb(
+ (int) (aSource * (1f - t) + aTarget * t),
+ (int) (rSource * (1f - t) + rTarget * t),
+ (int) (gSource * (1f - t) + gTarget * t),
+ (int) (bSource * (1f - t) + bTarget * t));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java
new file mode 100644
index 0000000..0a02573
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewWrapper.java
@@ -0,0 +1,56 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * Wraps the actual notification content view; used to implement behaviors which are different for
+ * the individual templates and custom views.
+ */
+public abstract class NotificationViewWrapper {
+
+ protected final View mView;
+
+ public static NotificationViewWrapper wrap(Context ctx, View v) {
+
+ // TODO: Figure out a better way to find out which template the view is.
+ if (v.findViewById(com.android.internal.R.id.media_actions) != null) {
+ return new NotificationMediaViewWrapper(ctx, v);
+ } else if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
+ return new NotificationTemplateViewWrapper(ctx, v);
+ } else {
+ return new NotificationCustomViewWrapper(v);
+ }
+ }
+
+ protected NotificationViewWrapper(View view) {
+ mView = view;
+ }
+
+ /**
+ * In dark mode, we draw as little as possible, assuming a black background.
+ *
+ * @param dark whether we should display ourselves in dark mode
+ * @param fade whether to animate the transition if the mode changes
+ * @param delay if fading, the delay of the animation
+ */
+ public abstract void setDark(boolean dark, boolean fade, long delay);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 9154a48..418c57f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -48,6 +48,7 @@ public class SignalClusterView
private int mMobileStrengthId = 0, mMobileTypeId = 0;
private boolean mIsAirplaneMode = false;
private int mAirplaneIconId = 0;
+ private int mAirplaneContentDescription;
private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
private boolean mIsMobileTypeIconWide;
@@ -160,9 +161,10 @@ public class SignalClusterView
}
@Override
- public void setIsAirplaneMode(boolean is, int airplaneIconId) {
+ public void setIsAirplaneMode(boolean is, int airplaneIconId, int contentDescription) {
mIsAirplaneMode = is;
mAirplaneIconId = airplaneIconId;
+ mAirplaneContentDescription = contentDescription;
apply();
}
@@ -236,6 +238,8 @@ public class SignalClusterView
if (mIsAirplaneMode) {
mAirplane.setImageResource(mAirplaneIconId);
+ mAirplane.setContentDescription(mAirplaneContentDescription != 0 ?
+ mContext.getString(mAirplaneContentDescription) : "");
mAirplane.setVisibility(View.VISIBLE);
} else {
mAirplane.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 f5c994a..3fca56d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -79,6 +79,7 @@ import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -821,7 +822,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
signalClusterQs.setNetworkController(mNetworkController);
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
- mNetworkController.addEmergencyLabelView(mHeader);
+ mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() {
+ @Override
+ public void setEmergencyCallsOnly(boolean emergencyOnly) {
+ mHeader.setShowEmergencyCallsOnly(emergencyOnly);
+ }
+ });
}
mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
@@ -830,13 +836,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
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);
- }
+ mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() {
+ @Override
+ public void setCarrierLabel(String label) {
+ mCarrierLabel.setText(label);
+ if (mNetworkController.hasMobileDataFeature()) {
+ if (TextUtils.isEmpty(label)) {
+ mCarrierLabel.setVisibility(View.GONE);
+ } else {
+ mCarrierLabel.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+ });
// set up the dynamic hide/show of the label
// TODO: uncomment, handle this for the Stack scroller aswell
@@ -2669,6 +2681,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void setInteracting(int barWindow, boolean interacting) {
+ final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting;
mInteractingWindows = interacting
? (mInteractingWindows | barWindow)
: (mInteractingWindows & ~barWindow);
@@ -2677,6 +2690,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
} else {
resumeSuspendedAutohide();
}
+ // manually dismiss the volume panel when interacting with the nav bar
+ if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) {
+ if (mVolumeComponent != null) {
+ mVolumeComponent.dismissNow();
+ }
+ }
checkBarModes();
}
@@ -3689,14 +3708,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) {
return;
}
- mNotificationPanel.setDozing(mDozing, mDozeScrimController.isPulsing() /*animate*/);
- if (mDozing) {
- mStackScroller.setDark(true, false /*animate*/);
- } else {
- mStackScroller.setDark(false, false /*animate*/);
- }
+ boolean animate = !mDozing && mDozeScrimController.isPulsing();
+ mNotificationPanel.setDozing(mDozing, animate);
+ mStackScroller.setDark(mDozing, animate);
mScrimController.setDozing(mDozing);
- mDozeScrimController.setDozing(mDozing, mDozeScrimController.isPulsing() /* animate */);
+ mDozeScrimController.setDozing(mDozing, animate);
}
public void updateStackScrollerState(boolean goingToFullShade) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 45a1386..8ce608c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -122,7 +122,7 @@ public class QSTileHost implements QSTile.Host {
tile.userSwitch(newUserId);
}
mSecurity.onUserSwitched(newUserId);
- mNetwork.onUserSwitched(newUserId);
+ mNetwork.getAccessPointController().onUserSwitched(newUserId);
mObserver.register();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index 0a385d7..6fec97e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -36,15 +36,13 @@ import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPointCallback;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public class AccessPointController {
+public class AccessPointControllerImpl implements NetworkController.AccessPointController {
private static final String TAG = "AccessPointController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -69,7 +67,7 @@ public class AccessPointController {
private boolean mScanning;
private int mCurrentUser;
- public AccessPointController(Context context) {
+ public AccessPointControllerImpl(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -81,25 +79,28 @@ public class AccessPointController {
new UserHandle(mCurrentUser));
}
- void onUserSwitched(int newUserId) {
+ public void onUserSwitched(int newUserId) {
mCurrentUser = newUserId;
}
- public void addCallback(AccessPointCallback callback) {
+ @Override
+ public void addAccessPointCallback(AccessPointCallback callback) {
if (callback == null || mCallbacks.contains(callback)) return;
if (DEBUG) Log.d(TAG, "addCallback " + callback);
mCallbacks.add(callback);
mReceiver.setListening(!mCallbacks.isEmpty());
}
- public void removeCallback(AccessPointCallback callback) {
+ @Override
+ public void removeAccessPointCallback(AccessPointCallback callback) {
if (callback == null) return;
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
mCallbacks.remove(callback);
mReceiver.setListening(!mCallbacks.isEmpty());
}
- public void scan() {
+ @Override
+ public void scanForAccessPoints() {
if (mScanning) return;
if (DEBUG) Log.d(TAG, "scan!");
mScanning = mWifiManager.startScan();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
index 7ac2a98..b7c74e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -33,11 +33,5 @@ public class AccessibilityContentDescriptions {
R.string.accessibility_wifi_three_bars,
R.string.accessibility_wifi_signal_full
};
- static final int[] WIMAX_CONNECTION_STRENGTH = {
- R.string.accessibility_no_wimax,
- R.string.accessibility_wimax_one_bar,
- R.string.accessibility_wimax_two_bars,
- R.string.accessibility_wimax_three_bars,
- R.string.accessibility_wimax_signal_full
- };
+ static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
index 33d68bf..20f0a83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
@@ -38,12 +38,10 @@ import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;
-import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
-
import java.util.Date;
import java.util.Locale;
-public class MobileDataController {
+public class MobileDataControllerImpl implements NetworkController.MobileDataController {
private static final String TAG = "MobileDataController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -61,8 +59,9 @@ public class MobileDataController {
private INetworkStatsSession mSession;
private Callback mCallback;
+ private NetworkControllerImpl mNetworkController;
- public MobileDataController(Context context) {
+ public MobileDataControllerImpl(Context context) {
mContext = context;
mTelephonyManager = TelephonyManager.from(context);
mConnectivityManager = ConnectivityManager.from(context);
@@ -71,6 +70,10 @@ public class MobileDataController {
mPolicyManager = NetworkPolicyManager.from(mContext);
}
+ public void setNetworkController(NetworkControllerImpl networkController) {
+ mNetworkController = networkController;
+ }
+
private INetworkStatsSession getSession() {
if (mSession == null) {
try {
@@ -155,6 +158,9 @@ public class MobileDataController {
} else {
usage.warningLevel = DEFAULT_WARNING_LEVEL;
}
+ if (usage != null) {
+ usage.carrier = mNetworkController.getMobileNetworkName();
+ }
return usage;
} catch (RemoteException e) {
return warn("remote call failed");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index bb29d01..b024f58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -22,6 +22,8 @@ public interface NetworkController {
void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
void setWifiEnabled(boolean enabled);
+ AccessPointController getAccessPointController();
+ MobileDataController getMobileDataController();
public interface NetworkSignalChangedCallback {
void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId,
@@ -36,38 +38,50 @@ public interface NetworkController {
void onMobileDataEnabled(boolean enabled);
}
- void addAccessPointCallback(AccessPointCallback callback);
- void removeAccessPointCallback(AccessPointCallback callback);
- void scanForAccessPoints();
- boolean connect(AccessPoint ap);
- boolean isMobileDataSupported();
- boolean isMobileDataEnabled();
- void setMobileDataEnabled(boolean enabled);
- DataUsageInfo getDataUsageInfo();
- boolean canConfigWifi();
- void onUserSwitched(int newUserId);
+ /**
+ * Tracks changes in access points. Allows listening for changes, scanning for new APs,
+ * and connecting to new ones.
+ */
+ public interface AccessPointController {
+ void addAccessPointCallback(AccessPointCallback callback);
+ void removeAccessPointCallback(AccessPointCallback callback);
+ void scanForAccessPoints();
+ boolean connect(AccessPoint ap);
+ boolean canConfigWifi();
+ void onUserSwitched(int newUserId);
- public interface AccessPointCallback {
- void onAccessPointsChanged(AccessPoint[] accessPoints);
- }
+ public interface AccessPointCallback {
+ void onAccessPointsChanged(AccessPoint[] accessPoints);
+ }
- public static class AccessPoint {
- public static final int NO_NETWORK = -1; // see WifiManager
+ public static class AccessPoint {
+ public static final int NO_NETWORK = -1; // see WifiManager
- public int networkId;
- public int iconId;
- public String ssid;
- public boolean isConnected;
- public boolean isConfigured;
- public boolean hasSecurity;
- public int level; // 0 - 5
+ public int networkId;
+ public int iconId;
+ public String ssid;
+ public boolean isConnected;
+ public boolean isConfigured;
+ public boolean hasSecurity;
+ public int level; // 0 - 5
+ }
}
- public static class DataUsageInfo {
- public String carrier;
- public String period;
- public long limitLevel;
- public long warningLevel;
- public long usageLevel;
+ /**
+ * Tracks mobile data support and usage.
+ */
+ public interface MobileDataController {
+ boolean isMobileDataSupported();
+ boolean isMobileDataEnabled();
+ void setMobileDataEnabled(boolean enabled);
+ DataUsageInfo getDataUsageInfo();
+
+ public static class DataUsageInfo {
+ public String carrier;
+ public String period;
+ public long limitLevel;
+ public long warningLevel;
+ public long usageLevel;
+ }
}
}
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 0caded5..5a97c75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -26,7 +26,6 @@ import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.net.wimax.WimaxManagerConstants;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
@@ -37,9 +36,8 @@ import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
+import android.text.format.DateFormat;
import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IccCardConstants;
@@ -48,130 +46,66 @@ import com.android.internal.telephony.cdma.EriInfo;
import com.android.internal.util.AsyncChannel;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarHeaderView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
/** Platform implementation of the network controller. **/
public class NetworkControllerImpl extends BroadcastReceiver
implements NetworkController, DemoMode {
// debug
- static final String TAG = "StatusBar.NetworkController";
- static final boolean DEBUG = false;
- static final boolean CHATTY = false; // additional diagnostics, but not logspew
-
- // telephony
- boolean mHspaDataDistinguishable;
- final TelephonyManager mPhone;
- boolean mDataConnected;
- IccCardConstants.State mSimState = IccCardConstants.State.READY;
- int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
- int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- int mDataState = TelephonyManager.DATA_DISCONNECTED;
- int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
- ServiceState mServiceState;
- SignalStrength mSignalStrength;
- int[] mDataIconList = TelephonyIcons.DATA_G[0];
- String mNetworkName;
- String mNetworkNameDefault;
- String mNetworkNameSeparator;
- int mPhoneSignalIconId;
- int mQSPhoneSignalIconId;
- int mDataDirectionIconId; // data + data direction on phones
- int mDataSignalIconId;
- int mDataTypeIconId;
- int mQSDataTypeIconId;
- int mAirplaneIconId;
- boolean mDataActive;
- boolean mNoSim;
- int mLastSignalLevel;
- boolean mShowPhoneRSSIForData = false;
- boolean mShowAtLeastThreeGees = false;
- boolean mAlwaysShowCdmaRssi = false;
-
- String mContentDescriptionPhoneSignal;
- String mContentDescriptionWifi;
- String mContentDescriptionWimax;
- String mContentDescriptionCombinedSignal;
- String mContentDescriptionDataType;
-
- // wifi
- final WifiManager mWifiManager;
- AsyncChannel mWifiChannel;
- boolean mWifiEnabled, mWifiConnected;
- int mWifiRssi, mWifiLevel;
- String mWifiSsid;
- int mWifiIconId = 0;
- int mQSWifiIconId = 0;
- int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE;
+ static final String TAG = "NetworkController";
+ static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ // additional diagnostics, but not logspew
+ static final boolean CHATTY = Log.isLoggable(TAG + ".Chat", Log.DEBUG);
+ // Save the previous states of all SignalController state info.
+ static final boolean RECORD_HISTORY = true;
+ // How many to save, must be a power of 2.
+ static final int HISTORY_SIZE = 16;
+
+ private static final int INET_CONDITION_THRESHOLD = 50;
+
+ private final Context mContext;
+ private final TelephonyManager mPhone;
+ private final WifiManager mWifiManager;
+ private final ConnectivityManager mConnectivityManager;
+ private final boolean mHasMobileDataFeature;
+
+ // Subcontrollers.
+ @VisibleForTesting
+ final WifiSignalController mWifiSignalController;
+ @VisibleForTesting
+ final MobileSignalController mMobileSignalController;
+ private final AccessPointController mAccessPoints;
+ private final MobileDataControllerImpl mMobileDataController;
// bluetooth
private boolean mBluetoothTethered = false;
- private 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;
// 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;
-
- private int mInetCondition = 0;
- private int mLastInetCondition = 0;
- private static final int INET_CONDITION_THRESHOLD = 50;
+ private boolean mInetCondition; // Used for Logging and demo.
+ // States that don't belong to a subcontroller.
private boolean mAirplaneMode = false;
- private boolean mLastAirplaneMode = true;
-
private Locale mLocale = null;
- private Locale mLastLocale = null;
-
- // our ui
- Context mContext;
- ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>();
- ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>();
- ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
- ArrayList<StatusBarHeaderView> mEmergencyViews = new ArrayList<>();
- ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
- ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
- new ArrayList<NetworkSignalChangedCallback>();
- int mLastPhoneSignalIconId = -1;
- int mLastDataDirectionIconId = -1;
- int mLastWifiIconId = -1;
- int mLastWimaxIconId = -1;
- int mLastCombinedSignalIconId = -1;
- int mLastDataTypeIconId = -1;
- String mLastCombinedLabel = "";
- private boolean mHasMobileDataFeature;
-
- boolean mDataAndWifiStacked = false;
-
- public interface SignalCluster {
- void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
- void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean isTypeIconWide);
- void setIsAirplaneMode(boolean is, int airplaneIcon);
- }
-
- private final AccessPointController mAccessPoints;
- private final MobileDataController mMobileDataController;
- private final ConnectivityManager mConnectivityManager;
+ // All the callbacks.
+ private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>();
+ private ArrayList<CarrierLabelListener> mCarrierListeners =
+ new ArrayList<CarrierLabelListener>();
+ private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
+ private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
+ new ArrayList<NetworkSignalChangedCallback>();
/**
* Construct this controller object and register for updates.
@@ -179,68 +113,51 @@ public class NetworkControllerImpl extends BroadcastReceiver
public NetworkControllerImpl(Context context) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
- (WifiManager) context.getSystemService(Context.WIFI_SERVICE));
+ (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
+ Config.readConfig(context), new AccessPointControllerImpl(context),
+ new MobileDataControllerImpl(context));
registerListeners();
}
@VisibleForTesting
NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
- TelephonyManager telephonyManager, WifiManager wifiManager) {
+ TelephonyManager telephonyManager, WifiManager wifiManager, Config config,
+ AccessPointControllerImpl accessPointController,
+ MobileDataControllerImpl mobileDataController) {
mContext = context;
- final Resources res = context.getResources();
mConnectivityManager = connectivityManager;
mHasMobileDataFeature =
mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
- mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
- mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
- mAlwaysShowCdmaRssi = res.getBoolean(
- com.android.internal.R.bool.config_alwaysUseCdmaRssi);
-
- // set up the default wifi icon, used when no radios have ever appeared
- updateWifiIcons();
- updateWimaxIcons();
-
// telephony
mPhone = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- mHspaDataDistinguishable = mContext.getResources().getBoolean(
- R.bool.config_hspa_data_distinguishable);
- mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator);
- mNetworkNameDefault = mContext.getString(
- com.android.internal.R.string.lockscreen_carrier_default);
- mNetworkName = mNetworkNameDefault;
// wifi
mWifiManager = wifiManager;
- Handler handler = new WifiHandler();
- mWifiChannel = new AsyncChannel();
- Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
- if (wifiMessenger != null) {
- mWifiChannel.connect(mContext, handler, wifiMessenger);
- }
-
- // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
- updateAirplaneMode();
- mLastLocale = mContext.getResources().getConfiguration().locale;
- mAccessPoints = new AccessPointController(mContext);
- mMobileDataController = new MobileDataController(mContext);
- mMobileDataController.setCallback(new MobileDataController.Callback() {
+ mLocale = mContext.getResources().getConfiguration().locale;
+ mAccessPoints = accessPointController;
+ mMobileDataController = mobileDataController;
+ mMobileDataController.setNetworkController(this);
+ // TODO: Find a way to move this into MobileDataController.
+ mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() {
@Override
public void onMobileDataEnabled(boolean enabled) {
notifyMobileDataEnabled(enabled);
}
});
+ mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
+ mSignalsChangedCallbacks, mSignalClusters, this);
+ mMobileSignalController = new MobileSignalController(mContext, config,
+ mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, this);
+
+ // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
+ updateAirplaneMode(true);
}
private void registerListeners() {
- mPhone.listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_SERVICE_STATE
- | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
- | PhoneStateListener.LISTEN_CALL_STATE
- | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
- | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+ mMobileSignalController.registerListener();
// broadcasts
IntentFilter filter = new IntentFilter();
@@ -253,29 +170,38 @@ public class NetworkControllerImpl extends BroadcastReceiver
filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mWimaxSupported = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_wimaxEnabled);
- if(mWimaxSupported) {
- filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION);
- filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION);
- filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION);
- }
mContext.registerReceiver(this, filter);
}
+ private void unregisterListeners() {
+ mMobileSignalController.unregisterListener();
+ mContext.unregisterReceiver(this);
+ }
+
@Override
- public boolean canConfigWifi() {
- return mAccessPoints.canConfigWifi();
+ public AccessPointController getAccessPointController() {
+ return mAccessPoints;
}
@Override
- public void onUserSwitched(int newUserId) {
- mAccessPoints.onUserSwitched(newUserId);
+ public MobileDataController getMobileDataController() {
+ return mMobileDataController;
+ }
+
+ public void addEmergencyListener(EmergencyListener listener) {
+ mEmergencyListeners.add(listener);
+ refreshCarrierLabel();
+ }
+
+ public void addCarrierLabel(CarrierLabelListener listener) {
+ mCarrierListeners.add(listener);
+ refreshCarrierLabel();
}
private void notifyMobileDataEnabled(boolean enabled) {
- for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
- cb.onMobileDataEnabled(enabled);
+ int length = mSignalsChangedCallbacks.size();
+ for (int i = 0; i < length; i++) {
+ mSignalsChangedCallbacks.get(i).onMobileDataEnabled(enabled);
}
}
@@ -287,34 +213,40 @@ public class NetworkControllerImpl extends BroadcastReceiver
return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
}
- public boolean isEmergencyOnly() {
- return (mServiceState != null && mServiceState.isEmergencyOnly());
- }
-
- public void addCombinedLabelView(TextView v) {
- mCombinedLabelViews.add(v);
+ public String getMobileNetworkName() {
+ return mMobileSignalController.mCurrentState.networkName;
}
- public void addMobileLabelView(TextView v) {
- mMobileLabelViews.add(v);
+ public boolean isEmergencyOnly() {
+ return mMobileSignalController.isEmergencyOnly();
}
- public void addWifiLabelView(TextView v) {
- mWifiLabelViews.add(v);
- }
+ /**
+ * Emergency status may have changed (triggered by MobileSignalController),
+ * so we should recheck and send out the state to listeners.
+ */
+ void recalculateEmergency() {
+ final boolean emergencyOnly = isEmergencyOnly();
- public void addEmergencyLabelView(StatusBarHeaderView v) {
- mEmergencyViews.add(v);
+ int length = mEmergencyListeners.size();
+ for (int i = 0; i < length; i++) {
+ mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly);
+ }
}
public void addSignalCluster(SignalCluster cluster) {
mSignalClusters.add(cluster);
- refreshSignalCluster(cluster);
+ cluster.setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON,
+ R.string.accessibility_airplane_mode);
+ mWifiSignalController.notifyListeners();
+ mMobileSignalController.notifyListeners();
}
public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
mSignalsChangedCallbacks.add(cb);
- notifySignalsChangedCallbacks(cb);
+ cb.onAirplaneModeChanged(mAirplaneMode);
+ mWifiSignalController.notifyListeners();
+ mMobileSignalController.notifyListeners();
}
public void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
@@ -322,26 +254,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
- public void addAccessPointCallback(AccessPointCallback callback) {
- mAccessPoints.addCallback(callback);
- }
-
- @Override
- public void removeAccessPointCallback(AccessPointCallback callback) {
- mAccessPoints.removeCallback(callback);
- }
-
- @Override
- public void scanForAccessPoints() {
- mAccessPoints.scan();
- }
-
- @Override
- public boolean connect(AccessPoint ap) {
- return mAccessPoints.connect(ap);
- }
-
- @Override
public void setWifiEnabled(final boolean enabled) {
new AsyncTask<Void, Void, Void>() {
@Override
@@ -349,7 +261,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
// Disable tethering if enabling Wifi
final int wifiApState = mWifiManager.getWifiApState();
if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
- (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
+ (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
mWifiManager.setWifiApEnabled(null, false);
}
@@ -360,1275 +272,1250 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
- public DataUsageInfo getDataUsageInfo() {
- final DataUsageInfo info = mMobileDataController.getDataUsageInfo();
- if (info != null) {
- info.carrier = mNetworkName;
+ public void onReceive(Context context, Intent intent) {
+ if (CHATTY) {
+ Log.d(TAG, "onReceive: intent=" + intent);
}
- return info;
+ final String action = intent.getAction();
+ if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
+ action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+ updateConnectivity(intent);
+ refreshCarrierLabel();
+ } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
+ refreshLocale();
+ refreshCarrierLabel();
+ } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
+ refreshLocale();
+ updateAirplaneMode(false);
+ refreshCarrierLabel();
+ }
+ mWifiSignalController.handleBroadcast(intent);
+ mMobileSignalController.handleBroadcast(intent);
}
- @Override
- public boolean isMobileDataSupported() {
- return mMobileDataController.isMobileDataSupported();
+ private void updateAirplaneMode(boolean force) {
+ boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
+ if (airplaneMode != mAirplaneMode || force) {
+ mAirplaneMode = airplaneMode;
+ mMobileSignalController.setAirplaneMode(mAirplaneMode);
+ notifyAirplaneCallbacks();
+ refreshCarrierLabel();
+ }
}
- @Override
- public boolean isMobileDataEnabled() {
- return mMobileDataController.isMobileDataEnabled();
+ private void refreshLocale() {
+ Locale current = mContext.getResources().getConfiguration().locale;
+ if (current.equals(mLocale)) {
+ mLocale = current;
+ notifyAllListeners();
+ }
}
- @Override
- public void setMobileDataEnabled(boolean enabled) {
- mMobileDataController.setMobileDataEnabled(enabled);
+ /**
+ * Turns inet condition into a boolean indexing for a specific network.
+ * returns 0 for bad connectivity on this network.
+ * returns 1 for good connectivity on this network.
+ */
+ private int inetConditionForNetwork(int networkType, boolean inetCondition) {
+ return (inetCondition && mConnectedNetworkType == networkType) ? 1 : 0;
}
- private boolean isTypeIconWide(int iconId) {
- return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId
- || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId;
+ private void notifyAllListeners() {
+ // Something changed, trigger everything!
+ notifyAirplaneCallbacks();
+ mMobileSignalController.notifyListeners();
+ mWifiSignalController.notifyListeners();
}
- private boolean isQsTypeIconWide(int iconId) {
- return TelephonyIcons.QS_ICON_LTE == iconId || TelephonyIcons.QS_ICON_1X == iconId
- || TelephonyIcons.QS_ICON_3G == iconId || TelephonyIcons.QS_ICON_4G == iconId;
+ private void notifyAirplaneCallbacks() {
+ int length = mSignalClusters.size();
+ for (int i = 0; i < length; i++) {
+ mSignalClusters.get(i).setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON,
+ R.string.accessibility_airplane_mode);
+ }
+ // update QS
+ int signalsChangedLength = mSignalsChangedCallbacks.size();
+ for (int i = 0; i < signalsChangedLength; i++) {
+ mSignalsChangedCallbacks.get(i).onAirplaneModeChanged(mAirplaneMode);
+ }
}
- public void refreshSignalCluster(SignalCluster cluster) {
- if (mDemoMode) return;
- cluster.setWifiIndicators(
- // only show wifi in the cluster if connected or if wifi-only
- mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
- mWifiIconId,
- mContentDescriptionWifi);
-
- if (mIsWimaxEnabled && mWimaxConnected) {
- // wimax is special
- cluster.setMobileDataIndicators(
- true,
- mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
- mDataTypeIconId,
- mContentDescriptionWimax,
- mContentDescriptionDataType,
- false /* isTypeIconWide */ );
- } else {
- // normal mobile data
- cluster.setMobileDataIndicators(
- mHasMobileDataFeature,
- mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
- mDataTypeIconId,
- mContentDescriptionPhoneSignal,
- mContentDescriptionDataType,
- isTypeIconWide(mDataTypeIconId));
- }
- cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
- }
+ /**
+ * Update the Inet conditions and what network we are connected to.
+ */
+ private void updateConnectivity(Intent intent) {
+ final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
- void notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb) {
- // only show wifi in the cluster if connected or if wifi-only
- boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
- String wifiDesc = wifiEnabled ?
- mWifiSsid : null;
- boolean wifiIn = wifiEnabled && mWifiSsid != null
- && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
- || mWifiActivity == WifiManager.DATA_ACTIVITY_IN);
- boolean wifiOut = wifiEnabled && mWifiSsid != null
- && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
- || mWifiActivity == WifiManager.DATA_ACTIVITY_OUT);
- cb.onWifiSignalChanged(mWifiEnabled, mWifiConnected, mQSWifiIconId, wifiIn, wifiOut,
- mContentDescriptionWifi, wifiDesc);
-
- boolean mobileIn = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
- || mDataActivity == TelephonyManager.DATA_ACTIVITY_IN);
- boolean mobileOut = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
- || mDataActivity == TelephonyManager.DATA_ACTIVITY_OUT);
- if (isEmergencyOnly()) {
- cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, null, mNoSim, isQsTypeIconWide(mQSDataTypeIconId));
+ // Are we connected at all, by any interface?
+ mConnected = info != null && info.isConnected();
+ if (mConnected) {
+ mConnectedNetworkType = info.getType();
+ mConnectedNetworkTypeName = info.getTypeName();
} else {
- if (mIsWimaxEnabled && mWimaxConnected) {
- // Wimax is special
- cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim,
- isQsTypeIconWide(mQSDataTypeIconId));
- } else {
- // Normal mobile data
- cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim,
- isQsTypeIconWide(mQSDataTypeIconId));
- }
+ mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+ mConnectedNetworkTypeName = null;
}
- cb.onAirplaneModeChanged(mAirplaneMode);
- }
- public void setStackedMode(boolean stacked) {
- mDataAndWifiStacked = true;
- }
+ int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
- @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();
- } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
- updateSimState(intent);
- updateDataIcon();
- refreshViews();
- } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
- updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
- intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
- intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
- intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
- refreshViews();
- } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
- action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
- updateConnectivity(intent);
- refreshViews();
- } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
- refreshLocale();
- refreshViews();
- } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
- refreshLocale();
- updateAirplaneMode();
- refreshViews();
- } 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();
+ if (CHATTY) {
+ Log.d(TAG, "updateConnectivity: networkInfo=" + info);
+ Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
}
+
+ mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD;
+
+ 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
+ mMobileSignalController.setInetCondition(mInetCondition ? 1 : 0,
+ inetConditionForNetwork(mMobileSignalController.getNetworkType(), mInetCondition));
+ mWifiSignalController.setInetCondition(
+ inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition));
}
+ /**
+ * Recalculate and update the carrier label.
+ */
+ void refreshCarrierLabel() {
+ Context context = mContext;
- // ===== Telephony ==============================================================
+ WifiSignalController.WifiState wifiState = mWifiSignalController.getState();
+ MobileSignalController.MobileState mobileState = mMobileSignalController.getState();
+ String label = mMobileSignalController.getLabel("", mConnected, mHasMobileDataFeature);
- PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- @Override
- public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- if (DEBUG) {
- Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
- ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
- }
- mSignalStrength = signalStrength;
- updateTelephonySignalStrength();
- refreshViews();
+ // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore
+ // but stay for the sake of history.
+ if (mBluetoothTethered && !mHasMobileDataFeature) {
+ label = mContext.getString(R.string.bluetooth_tethered);
}
- @Override
- public void onServiceStateChanged(ServiceState state) {
- if (DEBUG) {
- Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
- + " dataState=" + state.getDataRegState());
- }
- mServiceState = state;
- updateTelephonySignalStrength();
- updateDataNetType();
- updateDataIcon();
- refreshViews();
+ final boolean ethernetConnected =
+ (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
+ if (ethernetConnected && !mHasMobileDataFeature) {
+ label = context.getString(R.string.ethernet_label);
}
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (DEBUG) {
- Log.d(TAG, "onCallStateChanged state=" + state);
- }
- // In cdma, if a voice call is made, RSSI should switch to 1x.
- if (isCdma()) {
- updateTelephonySignalStrength();
- refreshViews();
+ if (mAirplaneMode && (!mobileState.connected && !mobileState.isEmergency)) {
+ // combined values from connected wifi take precedence over airplane mode
+ if (wifiState.connected && mHasMobileDataFeature) {
+ // Suppress "No internet connection." from mobile if wifi connected.
+ label = "";
+ } else {
+ if (!mHasMobileDataFeature) {
+ label = context.getString(
+ R.string.status_bar_settings_signal_meter_disconnected);
+ }
}
+ } else if (!mobileState.dataConnected && !wifiState.connected && !mBluetoothTethered &&
+ !ethernetConnected && !mHasMobileDataFeature) {
+ // Pretty much no connection.
+ label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
}
- @Override
- public void onDataConnectionStateChanged(int state, int networkType) {
- if (DEBUG) {
- Log.d(TAG, "onDataConnectionStateChanged: state=" + state
- + " type=" + networkType);
- }
- mDataState = state;
- mDataNetType = networkType;
- updateDataNetType();
- updateDataIcon();
- refreshViews();
+ // for mobile devices, we always show mobile connection info here (SPN/PLMN)
+ // for other devices, we show whatever network is connected
+ // This is determined above by references to mHasMobileDataFeature.
+ int length = mCarrierListeners.size();
+ for (int i = 0; i < length; i++) {
+ mCarrierListeners.get(i).setCarrierLabel(label);
}
+ }
- @Override
- public void onDataActivity(int direction) {
- if (DEBUG) {
- Log.d(TAG, "onDataActivity: direction=" + direction);
- }
- mDataActivity = direction;
- updateDataIcon();
- refreshViews();
- }
- };
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("NetworkController state:");
+ pw.println(String.format(" %s network type %d (%s)",
+ mConnected ? "CONNECTED" : "DISCONNECTED",
+ mConnectedNetworkType, mConnectedNetworkTypeName));
+ pw.println(" - telephony ------");
+ pw.print(" hasVoiceCallingFeature()=");
+ pw.println(hasVoiceCallingFeature());
- private final 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;
- }
- 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;
+ pw.println(" - Bluetooth ----");
+ pw.print(" mBtReverseTethered=");
+ pw.println(mBluetoothTethered);
+
+ pw.println(" - connectivity ------");
+ pw.print(" mInetCondition=");
+ pw.println(mInetCondition);
+ pw.print(" mAirplaneMode=");
+ pw.println(mAirplaneMode);
+ pw.print(" mLocale=");
+ pw.println(mLocale);
+
+ mMobileSignalController.dump(pw);
+ mWifiSignalController.dump(pw);
+ }
+
+ private boolean mDemoMode;
+ private int mDemoInetCondition;
+ private WifiSignalController.WifiState mDemoWifiState;
+ private MobileSignalController.MobileState mDemoMobileState;
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+ if (!mDemoMode && command.equals(COMMAND_ENTER)) {
+ if (DEBUG) Log.d(TAG, "Entering demo mode");
+ unregisterListeners();
+ mDemoMode = true;
+ mDemoInetCondition = mInetCondition ? 1 : 0;
+ mDemoWifiState = mWifiSignalController.getState();
+ mDemoMobileState = mMobileSignalController.getState();
+ } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
+ if (DEBUG) Log.d(TAG, "Exiting demo mode");
+ mDemoMode = false;
+ mWifiSignalController.resetLastState();
+ mMobileSignalController.resetLastState();
+ registerListeners();
+ notifyAllListeners();
+ refreshCarrierLabel();
+ } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
+ String airplane = args.getString("airplane");
+ if (airplane != null) {
+ boolean show = airplane.equals("show");
+ int length = mSignalClusters.size();
+ for (int i = 0; i < length; i++) {
+ mSignalClusters.get(i).setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON,
+ R.string.accessibility_airplane_mode);
+ }
}
- else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
- mSimState = IccCardConstants.State.PUK_REQUIRED;
+ String fully = args.getString("fully");
+ if (fully != null) {
+ mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0;
+ mWifiSignalController.setInetCondition(mDemoInetCondition);
+ mMobileSignalController.setInetCondition(mDemoInetCondition, mDemoInetCondition);
+ }
+ String wifi = args.getString("wifi");
+ if (wifi != null) {
+ boolean show = wifi.equals("show");
+ String level = args.getString("level");
+ if (level != null) {
+ mDemoWifiState.level = level.equals("null") ? -1
+ : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
+ mDemoWifiState.connected = mDemoWifiState.level >= 0;
+ }
+ mDemoWifiState.enabled = show;
+ mWifiSignalController.notifyListeners();
}
- else {
- mSimState = IccCardConstants.State.NETWORK_LOCKED;
+ String mobile = args.getString("mobile");
+ if (mobile != null) {
+ boolean show = mobile.equals("show");
+ String datatype = args.getString("datatype");
+ if (datatype != null) {
+ mDemoMobileState.iconGroup =
+ datatype.equals("1x") ? TelephonyIcons.ONE_X :
+ datatype.equals("3g") ? TelephonyIcons.THREE_G :
+ datatype.equals("4g") ? TelephonyIcons.FOUR_G :
+ datatype.equals("e") ? TelephonyIcons.E :
+ datatype.equals("g") ? TelephonyIcons.G :
+ datatype.equals("h") ? TelephonyIcons.H :
+ datatype.equals("lte") ? TelephonyIcons.LTE :
+ datatype.equals("roam") ? TelephonyIcons.ROAMING :
+ TelephonyIcons.UNKNOWN;
+ }
+ int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
+ String level = args.getString("level");
+ if (level != null) {
+ mDemoMobileState.level = level.equals("null") ? -1
+ : Math.min(Integer.parseInt(level), icons[0].length - 1);
+ mDemoMobileState.connected = mDemoMobileState.level >= 0;
+ }
+ mDemoMobileState.enabled = show;
+ mMobileSignalController.notifyListeners();
}
- } else {
- mSimState = IccCardConstants.State.UNKNOWN;
+ refreshCarrierLabel();
}
- if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState);
- }
-
- private boolean isCdma() {
- return (mSignalStrength != null) && !mSignalStrength.isGsm();
}
- private boolean hasService() {
- boolean retVal;
- if (mServiceState != null) {
- // Consider the device to be in service if either voice or data service is available.
- // Some SIM cards are marketed as data-only and do not support voice service, and on
- // these SIM cards, we want to show signal bars for data service as well as the "no
- // service" or "emergency calls only" text that indicates that voice is not available.
- switch(mServiceState.getVoiceRegState()) {
- case ServiceState.STATE_POWER_OFF:
- retVal = false;
- break;
- case ServiceState.STATE_OUT_OF_SERVICE:
- case ServiceState.STATE_EMERGENCY_ONLY:
- retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
- break;
- default:
- retVal = true;
+ static class WifiSignalController extends
+ SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
+ private final WifiManager mWifiManager;
+ private final AsyncChannel mWifiChannel;
+ private final boolean mHasMobileData;
+
+ public WifiSignalController(Context context, boolean hasMobileData,
+ List<NetworkSignalChangedCallback> signalCallbacks,
+ List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+ super("WifiSignalController", context, ConnectivityManager.TYPE_WIFI, signalCallbacks,
+ signalClusters, networkController);
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mHasMobileData = hasMobileData;
+ Handler handler = new WifiHandler();
+ mWifiChannel = new AsyncChannel();
+ Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
+ if (wifiMessenger != null) {
+ mWifiChannel.connect(context, handler, wifiMessenger);
}
- } else {
- retVal = false;
+ // WiFi only has one state.
+ mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
+ "Wi-Fi Icons",
+ WifiIcons.WIFI_SIGNAL_STRENGTH,
+ WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
+ WifiIcons.WIFI_NO_NETWORK,
+ WifiIcons.QS_WIFI_NO_NETWORK,
+ WifiIcons.WIFI_NO_NETWORK,
+ WifiIcons.QS_WIFI_NO_NETWORK,
+ AccessibilityContentDescriptions.WIFI_NO_CONNECTION
+ );
}
- if (DEBUG) Log.d(TAG, "hasService: mServiceState=" + mServiceState + " retVal=" + retVal);
- return retVal;
- }
-
- private void updateAirplaneMode() {
- mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
- }
- private void refreshLocale() {
- mLocale = mContext.getResources().getConfiguration().locale;
- }
+ @Override
+ public WifiState cleanState() {
+ return new WifiState();
+ }
- private final void updateTelephonySignalStrength() {
- if (DEBUG) {
- Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService()
- + " ss=" + mSignalStrength);
- }
- if (!hasService()) {
- if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: !hasService()");
- mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
- mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
- mDataSignalIconId = R.drawable.stat_sys_signal_null;
- mContentDescriptionPhoneSignal = mContext.getString(
- AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
- } else {
- if (mSignalStrength == null) {
- if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
- mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
- mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
- mDataSignalIconId = R.drawable.stat_sys_signal_null;
- mContentDescriptionPhoneSignal = mContext.getString(
- AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
- } else {
- int iconLevel;
- int[] iconList;
- if (isCdma() && mAlwaysShowCdmaRssi) {
- mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel();
- if (DEBUG) {
- Log.d(TAG, "updateTelephonySignalStrength:"
- + " mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
- + " set to cdmaLevel=" + mSignalStrength.getCdmaLevel()
- + " instead of level=" + mSignalStrength.getLevel());
- }
- } else {
- mLastSignalLevel = iconLevel = mSignalStrength.getLevel();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyListeners() {
+ // only show wifi in the cluster if connected or if wifi-only
+ boolean wifiEnabled = mCurrentState.enabled
+ && (mCurrentState.connected || !mHasMobileData);
+ String wifiDesc = wifiEnabled ? mCurrentState.ssid : null;
+ boolean ssidPresent = wifiEnabled && mCurrentState.ssid != null;
+ String contentDescription = getStringIfExists(getContentDescription());
+ int length = mSignalsChangedCallbacks.size();
+ for (int i = 0; i < length; i++) {
+ mSignalsChangedCallbacks.get(i).onWifiSignalChanged(mCurrentState.enabled,
+ mCurrentState.connected, getQsCurrentIconId(),
+ ssidPresent && mCurrentState.activityIn,
+ ssidPresent && mCurrentState.activityOut, contentDescription, wifiDesc);
+ }
- if (isRoaming()) {
- iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
- } else {
- iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
- }
- mPhoneSignalIconId = iconList[iconLevel];
- mQSPhoneSignalIconId =
- TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel];
- mContentDescriptionPhoneSignal = mContext.getString(
- AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
- mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
- if (DEBUG) Log.d(TAG, "updateTelephonySignalStrength: iconLevel=" + iconLevel);
+ int signalClustersLength = mSignalClusters.size();
+ for (int i = 0; i < signalClustersLength; i++) {
+ mSignalClusters.get(i).setWifiIndicators(
+ // only show wifi in the cluster if connected or if wifi-only
+ mCurrentState.enabled && (mCurrentState.connected || !mHasMobileData),
+ getCurrentIconId(), contentDescription);
}
}
- }
-
- private int inetConditionForNetwork(int networkType) {
- return (mInetCondition == 1 && mConnectedNetworkType == networkType) ? 1 : 0;
- }
- private final void updateDataNetType() {
- int inetCondition;
- mDataTypeIconId = mQSDataTypeIconId = 0;
- if (mIsWimaxEnabled && mWimaxConnected) {
- // wimax is a special 4g network not handled by telephony
- inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
- mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
- mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_4g;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_4g);
- } else {
- inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
- final boolean showDataTypeIcon = (inetCondition > 0);
- switch (mDataNetType) {
- case TelephonyManager.NETWORK_TYPE_UNKNOWN:
- if (!mShowAtLeastThreeGees) {
- mDataIconList = TelephonyIcons.DATA_G[inetCondition];
- mContentDescriptionDataType = "";
- break;
- } else {
- // fall through
- }
- case TelephonyManager.NETWORK_TYPE_EDGE:
- if (!mShowAtLeastThreeGees) {
- mDataIconList = TelephonyIcons.DATA_E[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_e : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_edge);
- break;
- } else {
- // fall through
- }
- case TelephonyManager.NETWORK_TYPE_UMTS:
- mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_3g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
- mContentDescriptionDataType = 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[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_h : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_3_5g);
+ /**
+ * Extract wifi state directly from broadcasts about changes in wifi state.
+ */
+ public void handleBroadcast(Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+ } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ final NetworkInfo networkInfo = (NetworkInfo)
+ intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+ mCurrentState.connected = networkInfo != null && networkInfo.isConnected();
+ // If Connected grab the signal strength and ssid.
+ if (mCurrentState.connected) {
+ // try getting it out of the intent first
+ WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
+ ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
+ : mWifiManager.getConnectionInfo();
+ if (info != null) {
+ mCurrentState.ssid = huntForSsid(info);
} else {
- mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_3g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_3g);
+ mCurrentState.ssid = null;
}
- break;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- if (!mShowAtLeastThreeGees) {
- // display 1xRTT for IS95A/B
- mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_1x : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_cdma);
- break;
- } else {
- // fall through
- }
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- if (!mShowAtLeastThreeGees) {
- mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_1x : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_cdma);
- break;
- } else {
- // fall through
- }
- 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[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_3g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_3g);
- break;
- case TelephonyManager.NETWORK_TYPE_LTE:
- boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE);
- if (show4GforLTE) {
- mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_4g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_4g);
- } else {
- mDataIconList = TelephonyIcons.DATA_LTE[inetCondition];
- mDataTypeIconId = showDataTypeIcon ? TelephonyIcons.ICON_LTE : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_lte);
- }
- break;
- default:
- if (!mShowAtLeastThreeGees) {
- mDataIconList = TelephonyIcons.DATA_G[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_gprs);
- } else {
- mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
- mDataTypeIconId = showDataTypeIcon ?
- R.drawable.stat_sys_data_fully_connected_3g : 0;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
- mContentDescriptionDataType = mContext.getString(
- R.string.accessibility_data_connection_3g);
- }
- break;
+ } else if (!mCurrentState.connected) {
+ mCurrentState.ssid = null;
+ }
+ } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+ mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
+ mCurrentState.level = WifiManager.calculateSignalLevel(
+ mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT);
}
- }
- if (isRoaming()) {
- mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
+ notifyListenersIfNecessary();
}
- }
- boolean isCdmaEri() {
- if (mServiceState != null) {
- final int iconIndex = mServiceState.getCdmaEriIconIndex();
- if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
- final int iconMode = mServiceState.getCdmaEriIconMode();
- if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
- || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
- return true;
+ private String huntForSsid(WifiInfo info) {
+ String ssid = info.getSSID();
+ if (ssid != null) {
+ return ssid;
+ }
+ // OK, it's not in the connectionInfo; we have to go hunting for it
+ List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
+ int length = networks.size();
+ for (int i = 0; i < length; i++) {
+ if (networks.get(i).networkId == info.getNetworkId()) {
+ return networks.get(i).SSID;
}
}
+ return null;
}
- return false;
- }
- private boolean isRoaming() {
- if (isCdma()) {
- return isCdmaEri();
- } else {
- return mServiceState != null && mServiceState.getRoaming();
+ @VisibleForTesting
+ void setActivity(int wifiActivity) {
+ mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+ || wifiActivity == WifiManager.DATA_ACTIVITY_IN;
+ mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+ || wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
+ notifyListenersIfNecessary();
}
- }
- private final void updateDataIcon() {
- int iconId;
- boolean visible = true;
-
- if (!isCdma()) {
- // GSM case, we have to check also the sim state
- if (mSimState == IccCardConstants.State.READY ||
- mSimState == IccCardConstants.State.UNKNOWN) {
- mNoSim = false;
- if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
- switch (mDataActivity) {
- 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;
- }
- mDataDirectionIconId = iconId;
- } else {
- iconId = 0;
- visible = false;
- }
- } else {
- iconId = 0;
- mNoSim = true;
- visible = false; // no SIM? no data
- }
- } else {
- // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
- if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
- switch (mDataActivity) {
- case TelephonyManager.DATA_ACTIVITY_IN:
- iconId = mDataIconList[1];
- break;
- case TelephonyManager.DATA_ACTIVITY_OUT:
- iconId = mDataIconList[2];
+ /**
+ * Handler to receive the data activity on wifi.
+ */
+ class WifiHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ mWifiChannel.sendMessage(Message.obtain(this,
+ AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
+ } else {
+ Log.e(mTag, "Failed to connect to wifi");
+ }
break;
- case TelephonyManager.DATA_ACTIVITY_INOUT:
- iconId = mDataIconList[3];
+ case WifiManager.DATA_ACTIVITY_NOTIFICATION:
+ setActivity(msg.arg1);
break;
- case TelephonyManager.DATA_ACTIVITY_DORMANT:
default:
- iconId = mDataIconList[0];
+ // Ignore
break;
}
- } else {
- iconId = 0;
- visible = false;
}
}
- mDataDirectionIconId = iconId;
- mDataConnected = visible;
- }
+ static class WifiState extends SignalController.State {
+ String ssid;
- void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
- if (false) {
- Log.d("CarrierLabel", "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);
+ @Override
+ public void copyFrom(State s) {
+ WifiState state = (WifiState) s;
+ ssid = state.ssid;
+ super.copyFrom(s);
}
- str.append(spn);
- something = true;
- }
- if (something) {
- mNetworkName = str.toString();
- } else {
- mNetworkName = mNetworkNameDefault;
- }
- }
- // ===== Wifi ===================================================================
+ @Override
+ protected void toString(StringBuilder builder) {
+ builder.append("ssid=").append(ssid).append(',');
+ super.toString(builder);
+ }
- class WifiHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
- if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
- mWifiChannel.sendMessage(Message.obtain(this,
- AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
- } else {
- Log.e(TAG, "Failed to connect to wifi");
- }
- break;
- case WifiManager.DATA_ACTIVITY_NOTIFICATION:
- if (msg.arg1 != mWifiActivity) {
- mWifiActivity = msg.arg1;
- refreshViews();
- }
- break;
- default:
- //Ignore
- break;
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o)
+ && Objects.equals(((WifiState) o).ssid, ssid);
}
}
}
- private void updateWifiState(Intent intent) {
- final String action = intent.getAction();
- if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
- } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- final NetworkInfo networkInfo = (NetworkInfo)
- intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
- boolean wasConnected = mWifiConnected;
- mWifiConnected = networkInfo != null && networkInfo.isConnected();
- // If Connected grab the signal strength and ssid
- if (mWifiConnected) {
- // try getting it out of the intent first
- WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
- if (info == null) {
- info = mWifiManager.getConnectionInfo();
+ static class MobileSignalController extends SignalController<MobileSignalController.MobileState,
+ MobileSignalController.MobileIconGroup> {
+ private final Config mConfig;
+ private final TelephonyManager mPhone;
+ private final String mNetworkNameDefault;
+ private final String mNetworkNameSeparator;
+
+ // @VisibleForDemoMode
+ Map<Integer, MobileIconGroup> mNetworkToIconLookup;
+
+ // Since some pieces of the phone state are interdependent we store it locally,
+ // this could potentially become part of MobileState for simplification/complication
+ // of code.
+ private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+ private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+ private ServiceState mServiceState;
+ private SignalStrength mSignalStrength;
+ private MobileIconGroup mDefaultIcons;
+
+ // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
+ // need listener lists anymore.
+ public MobileSignalController(Context context, Config config, boolean hasMobileData,
+ TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks,
+ List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+ super("MobileSignalController", context, ConnectivityManager.TYPE_MOBILE,
+ signalCallbacks, signalClusters, networkController);
+ mConfig = config;
+ mPhone = phone;
+ mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
+ mNetworkNameDefault = getStringIfExists(
+ com.android.internal.R.string.lockscreen_carrier_default);
+
+ mapIconSets();
+
+ mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault;
+ mLastState.enabled = mCurrentState.enabled = hasMobileData;
+ mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
+ }
+
+ /**
+ * Get (the mobile parts of) the carrier string.
+ *
+ * @param currentLabel can be used for concatenation, currently just empty
+ * @param connected whether the device has connection to the internet at all
+ * @param isMobileLabel whether to always return the network or just when data is connected
+ */
+ public String getLabel(String currentLabel, boolean connected, boolean isMobileLabel) {
+ if (!mCurrentState.enabled) {
+ return "";
+ } else {
+ String mobileLabel = "";
+ // 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 (mCurrentState.dataConnected) {
+ mobileLabel = mCurrentState.networkName;
+ } else if (connected || mCurrentState.isEmergency) {
+ if (mCurrentState.connected || mCurrentState.isEmergency) {
+ // The isEmergencyOnly test covers the case of a phone with no SIM
+ mobileLabel = mCurrentState.networkName;
+ }
+ } else {
+ mobileLabel = mContext
+ .getString(R.string.status_bar_settings_signal_meter_disconnected);
}
- if (info != null) {
- mWifiSsid = huntForSsid(info);
+
+ // Now for things that should only be shown when actually using mobile data.
+ if (isMobileLabel) {
+ return mobileLabel;
} else {
- mWifiSsid = null;
+ return mCurrentState.dataConnected ? mobileLabel : currentLabel;
}
- } else if (!mWifiConnected) {
- mWifiSsid = null;
}
- } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
- mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
- mWifiLevel = WifiManager.calculateSignalLevel(
- mWifiRssi, WifiIcons.WIFI_LEVEL_COUNT);
}
- updateWifiIcons();
- }
+ public int getDataContentDescription() {
+ return getIcons().mDataContentDescription;
+ }
- private void updateWifiIcons() {
- int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIFI);
- if (mWifiConnected) {
- mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
- mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
- mContentDescriptionWifi = mContext.getString(
- AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
- } else {
- if (mDataAndWifiStacked) {
- mWifiIconId = 0;
- mQSWifiIconId = 0;
- } else {
- mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0;
- mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0;
- }
- mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
+ public void setAirplaneMode(boolean airplaneMode) {
+ mCurrentState.airplaneMode = airplaneMode;
+ notifyListenersIfNecessary();
}
- }
- private String huntForSsid(WifiInfo info) {
- String ssid = info.getSSID();
- if (ssid != null) {
- return ssid;
+ public void setInetCondition(int inetCondition, int inetConditionForNetwork) {
+ // For mobile data, use general inet condition for phone signal indexing,
+ // and network specific for data indexing (I think this might be a bug, but
+ // keeping for now).
+ // TODO: Update with explanation of why.
+ mCurrentState.inetForNetwork = inetConditionForNetwork;
+ setInetCondition(inetCondition);
}
- // OK, it's not in the connectionInfo; we have to go hunting for it
- List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
- for (WifiConfiguration net : networks) {
- if (net.networkId == info.getNetworkId()) {
- return net.SSID;
- }
+
+ /**
+ * Start listening for phone state changes.
+ */
+ public void registerListener() {
+ mPhone.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SERVICE_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+ | PhoneStateListener.LISTEN_CALL_STATE
+ | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_DATA_ACTIVITY);
}
- return null;
- }
+ /**
+ * Stop listening for phone state changes.
+ */
+ public void unregisterListener() {
+ mPhone.listen(mPhoneStateListener, 0);
+ }
- // ===== Wimax ===================================================================
- private final void updateWimaxState(Intent intent) {
- final String action = intent.getAction();
- boolean wasConnected = mWimaxConnected;
- if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
- int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE,
- WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
- mIsWimaxEnabled = (wimaxStatus ==
- WimaxManagerConstants.NET_4G_STATE_ENABLED);
- } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) {
- mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0);
- } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
- mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE,
- WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
- mWimaxExtraState = intent.getIntExtra(
- WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL,
- WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
- mWimaxConnected = (mWimaxState ==
- WimaxManagerConstants.WIMAX_STATE_CONNECTED);
- mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE);
- }
- updateDataNetType();
- updateWimaxIcons();
- }
+ /**
+ * Produce a mapping of data network types to icon groups for simple and quick use in
+ * updateTelephony.
+ *
+ * TODO: See if config can change with locale, this may need to be regenerated on Locale
+ * change.
+ */
+ private void mapIconSets() {
+ mNetworkToIconLookup = new HashMap<Integer, MobileIconGroup>();
+
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
- private void updateWimaxIcons() {
- if (mIsWimaxEnabled) {
- if (mWimaxConnected) {
- int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
- if (mWimaxIdle)
- mWimaxIconId = WimaxIcons.WIMAX_IDLE;
- else
- mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[inetCondition][mWimaxSignal];
- mContentDescriptionWimax = mContext.getString(
- AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
+ if (!mConfig.showAtLeastThreeGees) {
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ TelephonyIcons.UNKNOWN);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
+
+ mDefaultIcons = TelephonyIcons.G;
} else {
- mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED;
- mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
+ TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
+ TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
+ TelephonyIcons.THREE_G);
+ mDefaultIcons = TelephonyIcons.THREE_G;
}
- } else {
- mWimaxIconId = 0;
- }
- }
- // ===== Full or limited Internet connectivity ==================================
+ MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+ if (mConfig.hspaDataDistinguishable) {
+ hGroup = TelephonyIcons.H;
+ }
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
- private void updateConnectivity(Intent intent) {
- if (CHATTY) {
- Log.d(TAG, "updateConnectivity: intent=" + intent);
+ if (mConfig.show4gForLte) {
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
+ } else {
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
+ }
}
- final NetworkInfo info = mConnectivityManager.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;
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyListeners() {
+ MobileIconGroup icons = getIcons();
+
+ String contentDescription = getStringIfExists(getContentDescription());
+ String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+ int qsTypeIcon = icons.mQsDataType[mCurrentState.inetForNetwork];
+ int length = mSignalsChangedCallbacks.size();
+ for (int i = 0; i < length; i++) {
+ mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
+ && !mCurrentState.isEmergency && !mCurrentState.airplaneMode,
+ getQsCurrentIconId(), contentDescription,
+ qsTypeIcon,
+ mCurrentState.dataConnected && mCurrentState.activityIn,
+ mCurrentState.dataConnected && mCurrentState.activityOut,
+ dataContentDescription,
+ mCurrentState.isEmergency ? null : mCurrentState.networkName,
+ mCurrentState.noSim,
+ // Only wide if actually showing something.
+ icons.mIsWide && qsTypeIcon != 0);
+ }
+ boolean showDataIcon = mCurrentState.inetForNetwork != 0
+ || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+ int typeIcon = showDataIcon ? icons.mDataType : 0;
+ int signalClustersLength = mSignalClusters.size();
+ for (int i = 0; i < signalClustersLength; i++) {
+ mSignalClusters.get(i).setMobileDataIndicators(
+ mCurrentState.enabled && !mCurrentState.airplaneMode,
+ getCurrentIconId(),
+ typeIcon,
+ contentDescription,
+ dataContentDescription,
+ // Only wide if actually showing something.
+ icons.mIsWide && typeIcon != 0);
+ }
}
- int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
-
- if (CHATTY) {
- Log.d(TAG, "updateConnectivity: networkInfo=" + info);
- Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
+ @Override
+ public MobileState cleanState() {
+ return new MobileState();
+ }
+
+ private boolean hasService() {
+ if (mServiceState != null) {
+ // Consider the device to be in service if either voice or data
+ // service is available. Some SIM cards are marketed as data-only
+ // and do not support voice service, and on these SIM cards, we
+ // want to show signal bars for data service as well as the "no
+ // service" or "emergency calls only" text that indicates that voice
+ // is not available.
+ switch (mServiceState.getVoiceRegState()) {
+ case ServiceState.STATE_POWER_OFF:
+ return false;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+ default:
+ return true;
+ }
+ } else {
+ return false;
+ }
}
- mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
-
- if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
- mBluetoothTethered = info.isConnected();
- } else {
- mBluetoothTethered = false;
+ private boolean isCdma() {
+ return (mSignalStrength != null) && !mSignalStrength.isGsm();
}
- // We want to update all the icons, all at once, for any condition change
- updateDataNetType();
- updateWimaxIcons();
- updateDataIcon();
- updateTelephonySignalStrength();
- updateWifiIcons();
- }
-
-
- // ===== Update the views =======================================================
+ public boolean isEmergencyOnly() {
+ return (mServiceState != null && mServiceState.isEmergencyOnly());
+ }
- void refreshViews() {
- Context context = mContext;
+ private boolean isRoaming() {
+ if (isCdma()) {
+ final int iconMode = mServiceState.getCdmaEriIconMode();
+ return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
+ && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
+ || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
+ } else {
+ return mServiceState != null && mServiceState.getRoaming();
+ }
+ }
- int combinedSignalIconId = 0;
- String combinedLabel = "";
- String wifiLabel = "";
- String mobileLabel = "";
- int N;
- final boolean emergencyOnly = isEmergencyOnly();
+ public void handleBroadcast(Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+ String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+ final String lockedReason =
+ intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+ updateSimState(stateExtra, lockedReason);
+ updateTelephony();
+ } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
+ updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
+ intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
+ intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
+ intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
+ notifyListenersIfNecessary();
+ }
+ }
- if (!mHasMobileDataFeature) {
- mDataSignalIconId = mPhoneSignalIconId = 0;
- mQSPhoneSignalIconId = 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 (mDataConnected) {
- mobileLabel = mNetworkName;
- } else if (mConnected || emergencyOnly) {
- if (hasService() || emergencyOnly) {
- // The isEmergencyOnly test covers the case of a phone with no SIM
- mobileLabel = mNetworkName;
+ /**
+ * Determines the current sim state, based on a TelephonyIntents.ACTION_SIM_STATE_CHANGED
+ * broadcast.
+ */
+ private final void updateSimState(String stateExtra, String lockedReason) {
+ if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ mSimState = IccCardConstants.State.ABSENT;
+ } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ mSimState = IccCardConstants.State.READY;
+ } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ mSimState = IccCardConstants.State.PIN_REQUIRED;
+ } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ mSimState = IccCardConstants.State.PUK_REQUIRED;
} else {
- // Tablets, basically
- mobileLabel = "";
+ mSimState = IccCardConstants.State.NETWORK_LOCKED;
}
} else {
- mobileLabel
- = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+ mSimState = IccCardConstants.State.UNKNOWN;
}
+ if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState);
+ }
- // Now for things that should only be shown when actually using mobile data.
- if (mDataConnected) {
- combinedSignalIconId = mDataSignalIconId;
-
- combinedLabel = mobileLabel;
- combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
- mContentDescriptionCombinedSignal = mContentDescriptionDataType;
+ /**
+ * Updates the network's name based on incoming spn and plmn.
+ */
+ void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
+ if (CHATTY) {
+ Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ + " showPlmn=" + showPlmn + " plmn=" + plmn);
+ }
+ StringBuilder str = new StringBuilder();
+ if (showPlmn && plmn != null) {
+ str.append(plmn);
+ }
+ if (showSpn && spn != null) {
+ if (str.length() != 0) {
+ str.append(mNetworkNameSeparator);
+ }
+ str.append(spn);
+ }
+ if (str.length() != 0) {
+ mCurrentState.networkName = str.toString();
+ } else {
+ mCurrentState.networkName = mNetworkNameDefault;
}
}
- if (mWifiConnected) {
- if (mWifiSsid == null) {
- wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
+ /**
+ * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
+ * mDataState, and mSimState. It should be called any time one of these is updated.
+ * This will call listeners if necessary.
+ */
+ private final void updateTelephony() {
+ if (DEBUG) {
+ Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService()
+ + " ss=" + mSignalStrength);
+ }
+ mCurrentState.connected = hasService() && mSignalStrength != null;
+ if (mCurrentState.connected) {
+ if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
+ mCurrentState.level = mSignalStrength.getCdmaLevel();
+ } else {
+ mCurrentState.level = mSignalStrength.getLevel();
+ }
+ }
+ if (mNetworkToIconLookup.containsKey(mDataNetType)) {
+ mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
} else {
- wifiLabel = mWifiSsid;
- if (DEBUG) {
- wifiLabel += "xxxxXXXXxxxxXXXX";
+ mCurrentState.iconGroup = mDefaultIcons;
+ }
+ mCurrentState.dataConnected = mCurrentState.connected
+ && mDataState == TelephonyManager.DATA_CONNECTED;
+ if (!isCdma()) {
+ if (mSimState == IccCardConstants.State.READY ||
+ mSimState == IccCardConstants.State.UNKNOWN) {
+ mCurrentState.noSim = false;
+ } else {
+ mCurrentState.noSim = true;
+ // No sim, no data.
+ mCurrentState.dataConnected = false;
}
}
- combinedLabel = wifiLabel;
- combinedSignalIconId = mWifiIconId; // set by updateWifiIcons()
- mContentDescriptionCombinedSignal = mContentDescriptionWifi;
- } else {
- if (mHasMobileDataFeature) {
- wifiLabel = "";
- } else {
- wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
+ if (isRoaming()) {
+ mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+ }
+ if (isEmergencyOnly() != mCurrentState.isEmergency) {
+ mCurrentState.isEmergency = isEmergencyOnly();
+ mNetworkController.recalculateEmergency();
}
+ notifyListenersIfNecessary();
}
- if (mBluetoothTethered) {
- combinedLabel = mContext.getString(R.string.bluetooth_tethered);
- combinedSignalIconId = mBluetoothTetherIconId;
- mContentDescriptionCombinedSignal = mContext.getString(
- R.string.accessibility_bluetooth_tether);
+ @VisibleForTesting
+ void setActivity(int activity) {
+ mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+ || activity == TelephonyManager.DATA_ACTIVITY_IN;
+ mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+ || activity == TelephonyManager.DATA_ACTIVITY_OUT;
+ notifyListenersIfNecessary();
}
- final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
- if (ethernetConnected) {
- combinedLabel = context.getString(R.string.ethernet_label);
+ @Override
+ public void dump(PrintWriter pw) {
+ super.dump(pw);
+ pw.println(" mServiceState=" + mServiceState + ",");
+ pw.println(" mSignalStrength=" + mSignalStrength + ",");
+ pw.println(" mDataState=" + mDataState + ",");
+ pw.println(" mDataNetType=" + mDataNetType + ",");
}
- if (mAirplaneMode &&
- (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
- // Only display the flight-mode icon if not in "emergency calls only" mode.
-
- // look again; your radios are now airplanes
- mContentDescriptionPhoneSignal = mContext.getString(
- R.string.accessibility_airplane_mode);
- mAirplaneIconId = TelephonyIcons.FLIGHT_MODE_ICON;
- mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
- mQSPhoneSignalIconId = 0;
-
- // 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;
+ PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ if (DEBUG) {
+ Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
+ ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
}
- mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
- combinedSignalIconId = mDataSignalIconId;
+ mSignalStrength = signalStrength;
+ updateTelephony();
}
- }
- else if (!mDataConnected && !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
- combinedSignalIconId =
- mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId;
- mContentDescriptionCombinedSignal = mHasMobileDataFeature
- ? mContentDescriptionDataType : mContentDescriptionWifi;
+ @Override
+ public void onServiceStateChanged(ServiceState state) {
+ if (DEBUG) {
+ Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
+ + " dataState=" + state.getDataRegState());
+ }
+ mServiceState = state;
+ updateTelephony();
+ }
- int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ if (DEBUG) {
+ Log.d(TAG, "onDataConnectionStateChanged: state=" + state
+ + " type=" + networkType);
+ }
+ mDataState = state;
+ mDataNetType = networkType;
+ updateTelephony();
+ }
- mDataTypeIconId = 0;
- mQSDataTypeIconId = 0;
- if (isRoaming()) {
- mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
- mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
+ @Override
+ public void onDataActivity(int direction) {
+ if (DEBUG) {
+ Log.d(TAG, "onDataActivity: direction=" + direction);
+ }
+ setActivity(direction);
+ }
+ };
+
+ static class MobileIconGroup extends SignalController.IconGroup {
+ final int mDataContentDescription; // mContentDescriptionDataType
+ final int mDataType;
+ final boolean mIsWide;
+ final int[] mQsDataType;
+
+ public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+ int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+ int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
+ int[] qsDataType) {
+ super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
+ qsDiscState, discContentDesc);
+ mDataContentDescription = dataContentDesc;
+ mDataType = dataType;
+ mIsWide = isWide;
+ mQsDataType = qsDataType;
}
}
- if (mDemoMode) {
- mQSWifiIconId = mDemoWifiLevel < 0 ? R.drawable.ic_qs_wifi_no_network
- : WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel];
- mQSPhoneSignalIconId = mDemoMobileLevel < 0 ? R.drawable.ic_qs_signal_no_signal :
- TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mDemoInetCondition][mDemoMobileLevel];
- mQSDataTypeIconId = mDemoQSDataTypeIconId;
- }
-
- if (DEBUG) {
- Log.d(TAG, "refreshViews connected={"
- + (mWifiConnected?" wifi":"")
- + (mDataConnected?" data":"")
- + " } level="
- + ((mSignalStrength == null)?"??":Integer.toString(mSignalStrength.getLevel()))
- + " combinedSignalIconId=0x"
- + Integer.toHexString(combinedSignalIconId)
- + "/" + getResourceName(combinedSignalIconId)
- + " mobileLabel=" + mobileLabel
- + " wifiLabel=" + wifiLabel
- + " emergencyOnly=" + emergencyOnly
- + " combinedLabel=" + combinedLabel
- + " mAirplaneMode=" + mAirplaneMode
- + " mDataActivity=" + mDataActivity
- + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
- + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId)
- + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
- + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
- + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
- + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId)
- + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
- + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId)
- + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
- }
+ static class MobileState extends SignalController.State {
+ String networkName;
+ boolean noSim;
+ boolean dataConnected;
+ boolean isEmergency;
+ boolean airplaneMode;
+ int inetForNetwork;
- // update QS
- for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
- notifySignalsChangedCallbacks(cb);
- }
-
- if (mLastPhoneSignalIconId != mPhoneSignalIconId
- || mLastWifiIconId != mWifiIconId
- || mLastInetCondition != mInetCondition
- || mLastWimaxIconId != mWimaxIconId
- || mLastDataTypeIconId != mDataTypeIconId
- || mLastAirplaneMode != mAirplaneMode
- || mLastLocale != mLocale
- || mLastConnectedNetworkType != mConnectedNetworkType)
- {
- // NB: the mLast*s will be updated later
- for (SignalCluster cluster : mSignalClusters) {
- refreshSignalCluster(cluster);
+ @Override
+ public void copyFrom(State s) {
+ MobileState state = (MobileState) s;
+ noSim = state.noSim;
+ networkName = state.networkName;
+ dataConnected = state.dataConnected;
+ inetForNetwork = state.inetForNetwork;
+ isEmergency = state.isEmergency;
+ airplaneMode = state.airplaneMode;
+ super.copyFrom(s);
}
- }
- if (mLastAirplaneMode != mAirplaneMode) {
- mLastAirplaneMode = mAirplaneMode;
- }
+ @Override
+ protected void toString(StringBuilder builder) {
+ builder.append("noSim=").append(noSim).append(',');
+ builder.append("networkName=").append(networkName).append(',');
+ builder.append("dataConnected=").append(dataConnected).append(',');
+ builder.append("inetForNetwork=").append(inetForNetwork).append(',');
+ builder.append("isEmergency=").append(isEmergency).append(',');
+ builder.append("airplaneMode=").append(airplaneMode).append(',');
+ super.toString(builder);
+ }
- if (mLastLocale != mLocale) {
- mLastLocale = mLocale;
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o)
+ && Objects.equals(((MobileState) o).networkName, networkName)
+ && ((MobileState) o).noSim == noSim
+ && ((MobileState) o).dataConnected == dataConnected
+ && ((MobileState) o).isEmergency == isEmergency
+ && ((MobileState) o).airplaneMode == airplaneMode
+ && ((MobileState) o).inetForNetwork == inetForNetwork;
+ }
}
+ }
- // the phone icon on phones
- if (mLastPhoneSignalIconId != mPhoneSignalIconId) {
- mLastPhoneSignalIconId = mPhoneSignalIconId;
+ /**
+ * Common base class for handling signal for both wifi and mobile data.
+ */
+ static abstract class SignalController<T extends SignalController.State,
+ I extends SignalController.IconGroup> {
+ protected final String mTag;
+ protected final T mCurrentState;
+ protected final T mLastState;
+ protected final int mNetworkType;
+ protected final Context mContext;
+ // The owner of the SignalController (i.e. NetworkController will maintain the following
+ // lists and call notifyListeners whenever the list has changed to ensure everyone
+ // is aware of current state.
+ protected final List<NetworkSignalChangedCallback> mSignalsChangedCallbacks;
+ protected final List<SignalCluster> mSignalClusters;
+ protected final NetworkControllerImpl mNetworkController;
+
+ // Save the previous HISTORY_SIZE states for logging.
+ private final State[] mHistory;
+ // Where to copy the next state into.
+ private int mHistoryIndex;
+
+ public SignalController(String tag, Context context, int type,
+ List<NetworkSignalChangedCallback> signalCallbacks,
+ List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+ mTag = TAG + "::" + tag;
+ mNetworkController = networkController;
+ mNetworkType = type;
+ mContext = context;
+ mSignalsChangedCallbacks = signalCallbacks;
+ mSignalClusters = signalClusters;
+ mCurrentState = cleanState();
+ mLastState = cleanState();
+ if (RECORD_HISTORY) {
+ mHistory = new State[HISTORY_SIZE];
+ for (int i = 0; i < HISTORY_SIZE; i++) {
+ mHistory[i] = cleanState();
+ }
+ }
}
- // the data icon on phones
- if (mLastDataDirectionIconId != mDataDirectionIconId) {
- mLastDataDirectionIconId = mDataDirectionIconId;
+ public T getState() {
+ return mCurrentState;
}
- // the wifi icon on phones
- if (mLastWifiIconId != mWifiIconId) {
- mLastWifiIconId = mWifiIconId;
+ public int getNetworkType() {
+ return mNetworkType;
}
- if (mLastInetCondition != mInetCondition) {
- mLastInetCondition = mInetCondition;
+ public void setInetCondition(int inetCondition) {
+ mCurrentState.inetCondition = inetCondition;
+ notifyListenersIfNecessary();
}
- if (mLastConnectedNetworkType != mConnectedNetworkType) {
- mLastConnectedNetworkType = mConnectedNetworkType;
+ // @VisibleForDemoMode
+ /**
+ * Used at the end of demo mode to clear out any ugly state that it has created.
+ * Since we haven't had any callbacks, then isDirty will not have been triggered,
+ * so we can just take the last good state directly from there.
+ */
+ void resetLastState() {
+ mCurrentState.copyFrom(mLastState);
}
- // the wimax icon on phones
- if (mLastWimaxIconId != mWimaxIconId) {
- mLastWimaxIconId = mWimaxIconId;
- }
- // the combined data signal icon
- if (mLastCombinedSignalIconId != combinedSignalIconId) {
- mLastCombinedSignalIconId = combinedSignalIconId;
+ /**
+ * Determines if the state of this signal controller has changed and
+ * needs to trigger callbacks related to it.
+ */
+ public boolean isDirty() {
+ if (!mLastState.equals(mCurrentState)) {
+ if (DEBUG) {
+ Log.d(mTag, "Change in state from: " + mLastState + "\n"
+ + "\tto: " + mCurrentState);
+ }
+ return true;
+ }
+ return false;
}
- // the data network type overlay
- if (mLastDataTypeIconId != mDataTypeIconId) {
- mLastDataTypeIconId = mDataTypeIconId;
+ public void saveLastState() {
+ if (RECORD_HISTORY) {
+ recordLast();
+ }
+ // Updates the current time.
+ mCurrentState.time = System.currentTimeMillis();
+ mLastState.copyFrom(mCurrentState);
+ }
+
+ /**
+ * Gets the signal icon for QS based on current state of connected, enabled, and level.
+ */
+ public int getQsCurrentIconId() {
+ if (mCurrentState.connected) {
+ return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level];
+ } else if (mCurrentState.enabled) {
+ return getIcons().mQsDiscState;
+ } else {
+ return getIcons().mQsNullState;
+ }
}
- // 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);
+ /**
+ * Gets the signal icon for SB based on current state of connected, enabled, and level.
+ */
+ public int getCurrentIconId() {
+ if (mCurrentState.connected) {
+ return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level];
+ } else if (mCurrentState.enabled) {
+ return getIcons().mSbDiscState;
+ } else {
+ return getIcons().mSbNullState;
}
}
- // 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);
+ /**
+ * Gets the content description for the signal based on current state of connected and
+ * level.
+ */
+ public int getContentDescription() {
+ if (mCurrentState.connected) {
+ return getIcons().mContentDesc[mCurrentState.level];
} else {
- v.setVisibility(View.VISIBLE);
+ return getIcons().mDiscContentDesc;
}
}
- // mobile label
- 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);
+ protected void notifyListenersIfNecessary() {
+ if (isDirty()) {
+ saveLastState();
+ notifyListeners();
+ mNetworkController.refreshCarrierLabel();
}
}
- // e-call label
- N = mEmergencyViews.size();
- for (int i=0; i<N; i++) {
- StatusBarHeaderView v = mEmergencyViews.get(i);
- v.setShowEmergencyCallsOnly(emergencyOnly);
+ /**
+ * Returns the resource if resId is not 0, and an empty string otherwise.
+ */
+ protected String getStringIfExists(int resId) {
+ return resId != 0 ? mContext.getString(resId) : "";
}
- }
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NetworkController state:");
- pw.println(String.format(" %s network type %d (%s)",
- mConnected?"CONNECTED":"DISCONNECTED",
- mConnectedNetworkType, mConnectedNetworkTypeName));
- pw.println(" - telephony ------");
- pw.print(" hasVoiceCallingFeature()=");
- pw.println(hasVoiceCallingFeature());
- pw.print(" hasService()=");
- pw.println(hasService());
- pw.print(" mHspaDataDistinguishable=");
- pw.println(mHspaDataDistinguishable);
- pw.print(" mDataConnected=");
- pw.println(mDataConnected);
- pw.print(" mSimState=");
- pw.println(mSimState);
- pw.print(" mPhoneState=");
- pw.println(mPhoneState);
- pw.print(" mDataState=");
- pw.println(mDataState);
- pw.print(" mDataActivity=");
- pw.println(mDataActivity);
- pw.print(" mDataNetType=");
- pw.print(mDataNetType);
- pw.print("/");
- pw.println(TelephonyManager.getNetworkTypeName(mDataNetType));
- pw.print(" mServiceState=");
- pw.println(mServiceState);
- pw.print(" mSignalStrength=");
- pw.println(mSignalStrength);
- pw.print(" mLastSignalLevel=");
- pw.println(mLastSignalLevel);
- pw.print(" mNetworkName=");
- pw.println(mNetworkName);
- pw.print(" mNetworkNameDefault=");
- pw.println(mNetworkNameDefault);
- pw.print(" mNetworkNameSeparator=");
- pw.println(mNetworkNameSeparator.replace("\n","\\n"));
- pw.print(" mPhoneSignalIconId=0x");
- pw.print(Integer.toHexString(mPhoneSignalIconId));
- pw.print("/");
- pw.print(" mQSPhoneSignalIconId=0x");
- pw.print(Integer.toHexString(mQSPhoneSignalIconId));
- pw.print("/");
- pw.println(getResourceName(mPhoneSignalIconId));
- pw.print(" mDataDirectionIconId=");
- pw.print(Integer.toHexString(mDataDirectionIconId));
- pw.print("/");
- pw.println(getResourceName(mDataDirectionIconId));
- pw.print(" mDataSignalIconId=");
- pw.print(Integer.toHexString(mDataSignalIconId));
- pw.print("/");
- pw.println(getResourceName(mDataSignalIconId));
- pw.print(" mDataTypeIconId=");
- pw.print(Integer.toHexString(mDataTypeIconId));
- pw.print("/");
- pw.println(getResourceName(mDataTypeIconId));
- pw.print(" mQSDataTypeIconId=");
- pw.print(Integer.toHexString(mQSDataTypeIconId));
- pw.print("/");
- pw.println(getResourceName(mQSDataTypeIconId));
-
- 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.println(String.format(" mQSWifiIconId=0x%08x/%s",
- mQSWifiIconId, getResourceName(mQSWifiIconId)));
- 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));
+ protected I getIcons() {
+ return (I) mCurrentState.iconGroup;
}
- pw.println(" - Bluetooth ----");
- pw.print(" mBtReverseTethered=");
- pw.println(mBluetoothTethered);
+ /**
+ * Saves the last state of any changes, so we can log the current
+ * and last value of any state data.
+ */
+ protected void recordLast() {
+ mHistory[mHistoryIndex++ & (HISTORY_SIZE - 1)].copyFrom(mLastState);
+ }
- pw.println(" - connectivity ------");
- pw.print(" mInetCondition=");
- pw.println(mInetCondition);
+ public void dump(PrintWriter pw) {
+ pw.println(" - " + mTag + " -----");
+ pw.println(" Current State: " + mCurrentState);
+ if (RECORD_HISTORY) {
+ // Count up the states that actually contain time stamps, and only display those.
+ int size = 0;
+ for (int i = 0; i < HISTORY_SIZE; i++) {
+ if (mHistory[i].time != 0) size++;
+ }
+ // Print out the previous states in ordered number.
+ for (int i = mHistoryIndex + HISTORY_SIZE - 1;
+ i >= mHistoryIndex + HISTORY_SIZE - size; i--) {
+ pw.println(" Previous State(" + (mHistoryIndex + HISTORY_SIZE - i) + ": "
+ + mHistory[i & (HISTORY_SIZE - 1)]);
+ }
+ }
+ }
- pw.println(" - icons ------");
- pw.print(" mLastPhoneSignalIconId=0x");
- pw.print(Integer.toHexString(mLastPhoneSignalIconId));
- pw.print("/");
- pw.println(getResourceName(mLastPhoneSignalIconId));
- pw.print(" mLastDataDirectionIconId=0x");
- pw.print(Integer.toHexString(mLastDataDirectionIconId));
- pw.print("/");
- pw.println(getResourceName(mLastDataDirectionIconId));
- pw.print(" mLastWifiIconId=0x");
- pw.print(Integer.toHexString(mLastWifiIconId));
- pw.print("/");
- pw.println(getResourceName(mLastWifiIconId));
- pw.print(" mLastCombinedSignalIconId=0x");
- pw.print(Integer.toHexString(mLastCombinedSignalIconId));
- pw.print("/");
- pw.println(getResourceName(mLastCombinedSignalIconId));
- pw.print(" mLastDataTypeIconId=0x");
- pw.print(Integer.toHexString(mLastDataTypeIconId));
- pw.print("/");
- pw.println(getResourceName(mLastDataTypeIconId));
- pw.print(" mLastCombinedLabel=");
- pw.print(mLastCombinedLabel);
- pw.println("");
- }
+ /**
+ * Trigger callbacks based on current state. The callbacks should be completely
+ * based on current state, and only need to be called in the scenario where
+ * mCurrentState != mLastState.
+ */
+ public abstract void notifyListeners();
+
+ /**
+ * Generate a blank T.
+ */
+ public abstract T cleanState();
+
+ /*
+ * Holds icons for a given state. Arrays are generally indexed as inet
+ * state (full connectivity or not) first, and second dimension as
+ * signal strength.
+ */
+ static class IconGroup {
+ final int[][] mSbIcons;
+ final int[][] mQsIcons;
+ final int[] mContentDesc;
+ final int mSbNullState;
+ final int mQsNullState;
+ final int mSbDiscState;
+ final int mQsDiscState;
+ final int mDiscContentDesc;
+ // For logging.
+ final String mName;
+
+ public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+ int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+ int discContentDesc) {
+ mName = name;
+ mSbIcons = sbIcons;
+ mQsIcons = qsIcons;
+ mContentDesc = contentDesc;
+ mSbNullState = sbNullState;
+ mQsNullState = qsNullState;
+ mSbDiscState = sbDiscState;
+ mQsDiscState = qsDiscState;
+ mDiscContentDesc = discContentDesc;
+ }
- private String getResourceName(int resId) {
- if (resId != 0) {
- final Resources res = mContext.getResources();
- try {
- return res.getResourceName(resId);
- } catch (android.content.res.Resources.NotFoundException ex) {
- return "(unknown)";
+ @Override
+ public String toString() {
+ return "IconGroup(" + mName + ")";
}
- } else {
- return "(null)";
}
- }
- private boolean mDemoMode;
- private int mDemoInetCondition;
- private int mDemoWifiLevel;
- private int mDemoDataTypeIconId;
- private int mDemoQSDataTypeIconId;
- private int mDemoMobileLevel;
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- if (!mDemoMode && command.equals(COMMAND_ENTER)) {
- mDemoMode = true;
- mDemoWifiLevel = mWifiLevel;
- mDemoInetCondition = mInetCondition;
- mDemoDataTypeIconId = mDataTypeIconId;
- mDemoQSDataTypeIconId = mQSDataTypeIconId;
- mDemoMobileLevel = mLastSignalLevel;
- } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
- mDemoMode = false;
- for (SignalCluster cluster : mSignalClusters) {
- refreshSignalCluster(cluster);
+ static class State {
+ boolean connected;
+ boolean enabled;
+ boolean activityIn;
+ boolean activityOut;
+ int level;
+ IconGroup iconGroup;
+ int inetCondition;
+ int rssi; // Only for logging.
+
+ // Not used for comparison, just used for logging.
+ long time;
+
+ public void copyFrom(State state) {
+ connected = state.connected;
+ enabled = state.enabled;
+ level = state.level;
+ iconGroup = state.iconGroup;
+ inetCondition = state.inetCondition;
+ activityIn = state.activityIn;
+ activityOut = state.activityOut;
+ rssi = state.rssi;
+ time = state.time;
}
- refreshViews();
- } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
- String airplane = args.getString("airplane");
- if (airplane != null) {
- boolean show = airplane.equals("show");
- for (SignalCluster cluster : mSignalClusters) {
- cluster.setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON);
+
+ @Override
+ public String toString() {
+ if (time != 0) {
+ StringBuilder builder = new StringBuilder();
+ toString(builder);
+ return builder.toString();
+ } else {
+ return "Empty " + getClass().getSimpleName();
}
}
- String fully = args.getString("fully");
- if (fully != null) {
- mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0;
- }
- String wifi = args.getString("wifi");
- if (wifi != null) {
- boolean show = wifi.equals("show");
- String level = args.getString("level");
- if (level != null) {
- mDemoWifiLevel = level.equals("null") ? -1
- : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
- }
- int iconId = mDemoWifiLevel < 0 ? R.drawable.stat_sys_wifi_signal_null
- : WifiIcons.WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel];
- for (SignalCluster cluster : mSignalClusters) {
- cluster.setWifiIndicators(
- show,
- iconId,
- "Demo");
- }
- refreshViews();
+
+ protected void toString(StringBuilder builder) {
+ builder.append("connected=").append(connected).append(',')
+ .append("enabled=").append(enabled).append(',')
+ .append("level=").append(level).append(',')
+ .append("inetCondition=").append(inetCondition).append(',')
+ .append("iconGroup=").append(iconGroup).append(',')
+ .append("activityIn=").append(activityIn).append(',')
+ .append("activityOut=").append(activityOut).append(',')
+ .append("rssi=").append(rssi).append(',')
+ .append("lastModified=").append(DateFormat.format("MM-dd hh:mm:ss", time));
}
- String mobile = args.getString("mobile");
- if (mobile != null) {
- boolean show = mobile.equals("show");
- String datatype = args.getString("datatype");
- if (datatype != null) {
- mDemoDataTypeIconId =
- datatype.equals("1x") ? TelephonyIcons.ICON_1X :
- datatype.equals("3g") ? TelephonyIcons.ICON_3G :
- datatype.equals("4g") ? TelephonyIcons.ICON_4G :
- datatype.equals("e") ? R.drawable.stat_sys_data_fully_connected_e :
- datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g :
- datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h :
- datatype.equals("lte") ? TelephonyIcons.ICON_LTE :
- datatype.equals("roam") ? TelephonyIcons.ROAMING_ICON :
- 0;
- mDemoQSDataTypeIconId =
- datatype.equals("1x") ? TelephonyIcons.QS_ICON_1X :
- datatype.equals("3g") ? TelephonyIcons.QS_ICON_3G :
- datatype.equals("4g") ? TelephonyIcons.QS_ICON_4G :
- datatype.equals("e") ? R.drawable.ic_qs_signal_e :
- datatype.equals("g") ? R.drawable.ic_qs_signal_g :
- datatype.equals("h") ? R.drawable.ic_qs_signal_h :
- datatype.equals("lte") ? TelephonyIcons.QS_ICON_LTE :
- datatype.equals("roam") ? R.drawable.ic_qs_signal_r :
- 0;
- }
- int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
- String level = args.getString("level");
- if (level != null) {
- mDemoMobileLevel = level.equals("null") ? -1
- : Math.min(Integer.parseInt(level), icons[0].length - 1);
- }
- int iconId = mDemoMobileLevel < 0 ? R.drawable.stat_sys_signal_null :
- icons[mDemoInetCondition][mDemoMobileLevel];
- for (SignalCluster cluster : mSignalClusters) {
- cluster.setMobileDataIndicators(
- show,
- iconId,
- mDemoDataTypeIconId,
- "Demo",
- "Demo",
- isTypeIconWide(mDemoDataTypeIconId));
+
+ @Override
+ public boolean equals(Object o) {
+ if (!o.getClass().equals(getClass())) {
+ return false;
}
- refreshViews();
+ State other = (State) o;
+ return other.connected == connected
+ && other.enabled == enabled
+ && other.level == level
+ && other.inetCondition == inetCondition
+ && other.iconGroup == iconGroup
+ && other.activityIn == activityIn
+ && other.activityOut == activityOut
+ && other.rssi == rssi;
}
}
}
+
+ public interface SignalCluster {
+ void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
+
+ void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
+ String contentDescription, String typeContentDescription, boolean isTypeIconWide);
+
+ void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription);
+ }
+
+ public interface EmergencyListener {
+ void setEmergencyCallsOnly(boolean emergencyOnly);
+ }
+
+ public interface CarrierLabelListener {
+ void setCarrierLabel(String label);
+ }
+
+ @VisibleForTesting
+ static class Config {
+ boolean showAtLeastThreeGees = false;
+ boolean alwaysShowCdmaRssi = false;
+ boolean show4gForLte = false;
+ boolean hspaDataDistinguishable;
+
+ static Config readConfig(Context context) {
+ Config config = new Config();
+ Resources res = context.getResources();
+
+ config.showAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
+ config.alwaysShowCdmaRssi =
+ res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
+ config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
+ config.hspaDataDistinguishable =
+ res.getBoolean(R.bool.config_hspa_data_distinguishable);
+ return config;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 1f2b918..4091619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -17,11 +17,16 @@
package com.android.systemui.statusbar.policy;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.MobileSignalController.MobileIconGroup;
class TelephonyIcons {
//***** Signal strength icons
+ static final int TELEPHONY_NUM_LEVELS = 5;
+
//GSM/UMTS
+ static final int TELEPHONY_NO_NETWORK = R.drawable.stat_sys_signal_null;
+
static final int[][] TELEPHONY_SIGNAL_STRENGTH = {
{ R.drawable.stat_sys_signal_0,
R.drawable.stat_sys_signal_1,
@@ -35,6 +40,8 @@ class TelephonyIcons {
R.drawable.stat_sys_signal_4_fully }
};
+ static final int QS_TELEPHONY_NO_NETWORK = R.drawable.ic_qs_signal_no_signal;
+
static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = {
{ R.drawable.ic_qs_signal_0,
R.drawable.ic_qs_signal_1,
@@ -66,8 +73,6 @@ class TelephonyIcons {
R.drawable.ic_qs_signal_r
};
- static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH;
-
//***** Data connection icons
//GSM/UMTS
@@ -191,6 +196,9 @@ class TelephonyIcons {
static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+ static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
+ static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
+ static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
@@ -199,5 +207,137 @@ class TelephonyIcons {
static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
+
+ static final MobileIconGroup THREE_G = new MobileIconGroup(
+ "3G",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_3g,
+ TelephonyIcons.ICON_3G,
+ true,
+ TelephonyIcons.QS_DATA_3G
+ );
+
+ static final MobileIconGroup UNKNOWN = new MobileIconGroup(
+ "Unknown",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ 0, 0, false, new int[2]
+ );
+
+ static final MobileIconGroup E = new MobileIconGroup(
+ "E",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_edge,
+ TelephonyIcons.ICON_E,
+ false,
+ TelephonyIcons.QS_DATA_E
+ );
+
+ static final MobileIconGroup ONE_X = new MobileIconGroup(
+ "1X",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_cdma,
+ TelephonyIcons.ICON_1X,
+ true,
+ TelephonyIcons.QS_DATA_1X
+ );
+
+ static final MobileIconGroup G = new MobileIconGroup(
+ "G",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_gprs,
+ TelephonyIcons.ICON_G,
+ false,
+ TelephonyIcons.QS_DATA_G
+ );
+
+ static final MobileIconGroup H = new MobileIconGroup(
+ "H",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_3_5g,
+ TelephonyIcons.ICON_H,
+ false,
+ TelephonyIcons.QS_DATA_H
+ );
+
+ static final MobileIconGroup FOUR_G = new MobileIconGroup(
+ "4G",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_4g,
+ TelephonyIcons.ICON_4G,
+ true,
+ TelephonyIcons.QS_DATA_4G
+ );
+
+ static final MobileIconGroup LTE = new MobileIconGroup(
+ "LTE",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_lte,
+ TelephonyIcons.ICON_LTE,
+ true,
+ TelephonyIcons.QS_DATA_LTE
+ );
+
+ static final MobileIconGroup ROAMING = new MobileIconGroup(
+ "Roaming",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_roaming,
+ TelephonyIcons.ROAMING_ICON,
+ false,
+ TelephonyIcons.QS_DATA_R
+ );
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index 49af979..c56646f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -45,5 +45,8 @@ class WifiIcons {
R.drawable.ic_qs_wifi_full_4 }
};
+ static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network;
+ static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null;
+
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
deleted file mode 100644
index 4877828..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.policy;
-
-import com.android.systemui.statusbar.policy.TelephonyIcons;
-
-class WimaxIcons {
- static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH;
-
- static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0];
-
- static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index 3c93b19..3d4cda6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -33,6 +33,7 @@ public class AnimationFilter {
boolean animateHideSensitive;
boolean hasDelays;
boolean hasGoToFullShadeEvent;
+ boolean hasDarkEvent;
public AnimationFilter animateAlpha() {
animateAlpha = true;
@@ -98,6 +99,10 @@ public class AnimationFilter {
NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE) {
hasGoToFullShadeEvent = true;
}
+ if (events.get(i).animationType ==
+ NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_DARK) {
+ hasDarkEvent = true;
+ }
}
}
@@ -126,5 +131,6 @@ public class AnimationFilter {
animateHideSensitive = false;
hasDelays = false;
hasGoToFullShadeEvent = false;
+ hasDarkEvent = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index e63be97..c5f1161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2455,7 +2455,8 @@ public class NotificationStackScrollLayout extends ViewGroup
// ANIMATION_TYPE_DARK
new AnimationFilter()
- .animateDark(),
+ .animateDark()
+ .hasDelays(),
// ANIMATION_TYPE_GO_TO_FULL_SHADE
new AnimationFilter()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 4611370..0b1ce8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -154,7 +154,7 @@ public class StackScrollState {
child.setDimmed(state.dimmed, false /* animate */);
// apply dark
- child.setDark(state.dark, false /* animate */);
+ child.setDark(state.dark, false /* animate */, 0 /* delay */);
// apply hiding sensitive
child.setHideSensitive(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index a56440c..05077bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -46,6 +46,7 @@ public class StackStateAnimator {
public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
+ public static final int ANIMATION_DELAY_PER_ELEMENT_DARK = 24;
private static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
@@ -161,11 +162,12 @@ public class StackStateAnimator {
boolean scaleChanging = child.getScaleX() != viewState.scale;
boolean alphaChanging = alpha != child.getAlpha();
boolean heightChanging = viewState.height != child.getActualHeight();
+ boolean darkChanging = viewState.dark != child.isDark();
boolean topInsetChanging = viewState.clipTopAmount != child.getClipTopAmount();
boolean wasAdded = mNewAddChildren.contains(child);
boolean hasDelays = mAnimationFilter.hasDelays;
boolean isDelayRelevant = yTranslationChanging || zTranslationChanging || scaleChanging ||
- alphaChanging || heightChanging || topInsetChanging;
+ alphaChanging || heightChanging || topInsetChanging || darkChanging;
boolean noAnimation = wasAdded;
long delay = 0;
long duration = mCurrentLength;
@@ -242,7 +244,7 @@ public class StackStateAnimator {
&& !noAnimation);
// start dark animation
- child.setDark(viewState.dark, mAnimationFilter.animateDark && !noAnimation);
+ child.setDark(viewState.dark, mAnimationFilter.animateDark && !noAnimation, delay);
// apply speed bump state
child.setBelowSpeedBump(viewState.belowSpeedBump);
@@ -262,6 +264,9 @@ public class StackStateAnimator {
private long calculateChildAnimationDelay(StackScrollState.ViewState viewState,
StackScrollState finalState) {
+ if (mAnimationFilter.hasDarkEvent) {
+ return calculateDelayDark(viewState);
+ }
if (mAnimationFilter.hasGoToFullShadeEvent) {
return calculateDelayGoToFullShade(viewState);
}
@@ -309,6 +314,10 @@ public class StackStateAnimator {
return minDelay;
}
+ private long calculateDelayDark(StackScrollState.ViewState viewState) {
+ return viewState.notGoneIndex * ANIMATION_DELAY_PER_ELEMENT_DARK;
+ }
+
private long calculateDelayGoToFullShade(StackScrollState.ViewState viewState) {
float index = viewState.notGoneIndex;
index = (float) Math.pow(index, 0.7f);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index 31adc95..e3f8f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -21,4 +21,5 @@ import com.android.systemui.statusbar.policy.ZenModeController;
public interface VolumeComponent extends DemoMode {
ZenModeController getZenController();
+ void dismissNow();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index f12053c..351911c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -793,7 +793,7 @@ public class VolumePanel extends Handler implements DemoMode {
sc.icon.setAlpha(mDisabledAlpha);
sc.icon.setClickable(false);
} else if (fixedVolume ||
- (sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
+ (sc.streamType != mAudioManager.getMasterStreamType() && !isRinger && muted) ||
(sSafetyWarning != null)) {
sc.seekbarView.setEnabled(false);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 5232a17..7102c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -178,7 +178,7 @@ public class VolumeUI extends SystemUI {
@Override
public void dismiss() throws RemoteException {
- mPanel.postDismiss(0);
+ dismissNow();
}
@Override
@@ -190,6 +190,11 @@ public class VolumeUI extends SystemUI {
public void dispatchDemoCommand(String command, Bundle args) {
mPanel.dispatchDemoCommand(command, args);
}
+
+ @Override
+ public void dismissNow() {
+ mPanel.postDismiss(0);
+ }
}
private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 8b87522..5a90324 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -17,14 +17,20 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.systemui:com.android.keyguard
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../src) \
+ src/com/android/systemui/EventLogTags.logtags
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+ frameworks/base/packages/SystemUI/res \
+ frameworks/base/packages/Keyguard/res
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
LOCAL_PACKAGE_NAME := SystemUITests
-LOCAL_INSTRUMENTATION_FOR := SystemUI
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target Keyguard
# sign this with platform cert, so this test is allowed to inject key events into
# UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 1d319cf..e52806d 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -25,7 +25,7 @@
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.systemui"
+ android:targetPackage="com.android.systemui.tests"
android:label="Tests for SystemUI">
</instrumentation>
</manifest>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags b/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
new file mode 120000
index 0000000..2f243d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
@@ -0,0 +1 @@
+../../../../../src/com/android/systemui/EventLogTags.logtags \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
index 2935373..784d035 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
@@ -15,7 +15,7 @@
*/
package com.android.systemui.screenshot;
-import com.android.systemui.tests.R;
+import com.android.systemui.R;
import android.app.Activity;
import android.os.Bundle;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 97605ea..49fe1e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -17,6 +17,7 @@ import android.util.Log;
import com.android.internal.telephony.cdma.EriInfo;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SignalCluster;
import org.mockito.ArgumentCaptor;
@@ -44,6 +45,7 @@ public class NetworkControllerBaseTest extends AndroidTestCase {
protected ConnectivityManager mMockCm;
protected WifiManager mMockWm;
protected TelephonyManager mMockTm;
+ protected Config mConfig;
@Override
protected void setUp() throws Exception {
@@ -59,15 +61,19 @@ public class NetworkControllerBaseTest extends AndroidTestCase {
mSignalStrength = mock(SignalStrength.class);
mServiceState = mock(ServiceState.class);
- mSignalCluster = mock(SignalCluster.class);
- mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
- mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm);
+ mConfig = new Config();
+ mConfig.hspaDataDistinguishable = true;
+ mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+ mConfig, mock(AccessPointControllerImpl.class),
+ mock(MobileDataControllerImpl.class));
setupNetworkController();
}
protected void setupNetworkController() {
- mPhoneStateListener = mNetworkController.mPhoneStateListener;
+ mPhoneStateListener = mNetworkController.mMobileSignalController.mPhoneStateListener;
+ mSignalCluster = mock(SignalCluster.class);
+ mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
mNetworkController.addSignalCluster(mSignalCluster);
mNetworkController.addNetworkSignalChangedCallback(mNetworkSignalChangedCallback);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index ed76ae5..bb2ff7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -1,5 +1,7 @@
package com.android.systemui.statusbar.policy;
+import static org.mockito.Mockito.mock;
+
import android.net.ConnectivityManager;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
@@ -15,7 +17,9 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
// Turn off mobile network support.
Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
// Create a new NetworkController as this is currently handled in constructor.
- mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm);
+ mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+ mConfig, mock(AccessPointControllerImpl.class),
+ mock(MobileDataControllerImpl.class));
setupNetworkController();
verifyLastMobileDataIndicators(false, 0, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 4ffdff2..7f0a8f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -6,8 +6,6 @@ import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import com.android.systemui.R;
-
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -16,14 +14,10 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
private static final int MIN_RSSI = -100;
private static final int MAX_RSSI = -55;
- // TODO: Move this into WifiIcons, remove all R.drawable from NetworkControllerImpl.
- private static final int NULL_SIGNAL = R.drawable.stat_sys_wifi_signal_null;
- private static final int QS_NO_NET = R.drawable.ic_qs_wifi_no_network;
-
public void testWifiIcon() {
String testSsid = "Test SSID";
setWifiEnabled(true);
- verifyLastWifiIcon(false, NULL_SIGNAL);
+ verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
setWifiState(true, testSsid);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
@@ -42,10 +36,10 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
String testSsid = "Test SSID";
setWifiEnabled(false);
- verifyLastQsWifiIcon(false, false, 0, null);
+ verifyLastQsWifiIcon(false, false, WifiIcons.QS_WIFI_NO_NETWORK, null);
setWifiEnabled(true);
- verifyLastQsWifiIcon(true, false, QS_NO_NET, null);
+ verifyLastQsWifiIcon(true, false, WifiIcons.QS_WIFI_NO_NETWORK, null);
setWifiState(true, testSsid);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
@@ -118,8 +112,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
protected void setWifiActivity(int activity) {
// TODO: Not this, because this variable probably isn't sticking around.
- mNetworkController.mWifiActivity = activity;
- mNetworkController.refreshViews();
+ mNetworkController.mWifiSignalController.setActivity(activity);
}
protected void setWifiLevel(int level) {