Merge "Add "large text" accessibility option."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9b33600..5e37d06 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -54,7 +54,7 @@
<application android:label="@string/settings_label"
android:icon="@mipmap/ic_launcher_settings"
android:taskAffinity=""
- android:hardwareAccelerated="true">
+ android:hardwareAccelerated="false">
<!-- Settings -->
diff --git a/res/drawable-hdpi/data_sweep_left_activated.9.png b/res/drawable-hdpi/data_sweep_left_activated.9.png
index e91ccf5..28efd35 100644
--- a/res/drawable-hdpi/data_sweep_left_activated.9.png
+++ b/res/drawable-hdpi/data_sweep_left_activated.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_left_default.9.png b/res/drawable-hdpi/data_sweep_left_default.9.png
index 76f33a5..4b6f2df 100644
--- a/res/drawable-hdpi/data_sweep_left_default.9.png
+++ b/res/drawable-hdpi/data_sweep_left_default.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_limit_activated.9.png b/res/drawable-hdpi/data_sweep_limit_activated.9.png
index 4744037..59de0d3 100644
--- a/res/drawable-hdpi/data_sweep_limit_activated.9.png
+++ b/res/drawable-hdpi/data_sweep_limit_activated.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_limit_default.9.png b/res/drawable-hdpi/data_sweep_limit_default.9.png
index dea3a0b..d7f3a88 100644
--- a/res/drawable-hdpi/data_sweep_limit_default.9.png
+++ b/res/drawable-hdpi/data_sweep_limit_default.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_right_activated.9.png b/res/drawable-hdpi/data_sweep_right_activated.9.png
index afb15d6..ccd7ff9 100644
--- a/res/drawable-hdpi/data_sweep_right_activated.9.png
+++ b/res/drawable-hdpi/data_sweep_right_activated.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_right_default.9.png b/res/drawable-hdpi/data_sweep_right_default.9.png
index 9d3808f..1179fde 100644
--- a/res/drawable-hdpi/data_sweep_right_default.9.png
+++ b/res/drawable-hdpi/data_sweep_right_default.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_warning_activated.9.png b/res/drawable-hdpi/data_sweep_warning_activated.9.png
index 81a7aa8..9ecd28b 100644
--- a/res/drawable-hdpi/data_sweep_warning_activated.9.png
+++ b/res/drawable-hdpi/data_sweep_warning_activated.9.png
Binary files differ
diff --git a/res/drawable-hdpi/data_sweep_warning_default.9.png b/res/drawable-hdpi/data_sweep_warning_default.9.png
index e2485fe..ec2b9df 100644
--- a/res/drawable-hdpi/data_sweep_warning_default.9.png
+++ b/res/drawable-hdpi/data_sweep_warning_default.9.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_settings_battery.png b/res/drawable-hdpi/ic_settings_battery.png
new file mode 100755
index 0000000..e3b0fb3
--- /dev/null
+++ b/res/drawable-hdpi/ic_settings_battery.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_settings_development.png b/res/drawable-hdpi/ic_settings_development.png
new file mode 100755
index 0000000..e3b0fb3
--- /dev/null
+++ b/res/drawable-hdpi/ic_settings_development.png
Binary files differ
diff --git a/res/drawable-mdpi/data_grid_border.9.png b/res/drawable-mdpi/data_grid_border.9.png
new file mode 100644
index 0000000..85912b8
--- /dev/null
+++ b/res/drawable-mdpi/data_grid_border.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_grid_primary.9.png b/res/drawable-mdpi/data_grid_primary.9.png
new file mode 100644
index 0000000..0aa9143
--- /dev/null
+++ b/res/drawable-mdpi/data_grid_primary.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_grid_secondary.9.png b/res/drawable-mdpi/data_grid_secondary.9.png
new file mode 100644
index 0000000..7a09593
--- /dev/null
+++ b/res/drawable-mdpi/data_grid_secondary.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_left_activated.9.png b/res/drawable-mdpi/data_sweep_left_activated.9.png
new file mode 100644
index 0000000..fc6764a
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_left_activated.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_left_default.9.png b/res/drawable-mdpi/data_sweep_left_default.9.png
new file mode 100644
index 0000000..31343e7
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_left_default.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_limit_activated.9.png b/res/drawable-mdpi/data_sweep_limit_activated.9.png
new file mode 100644
index 0000000..b01d5f0
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_limit_activated.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_limit_default.9.png b/res/drawable-mdpi/data_sweep_limit_default.9.png
new file mode 100644
index 0000000..a59649a
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_limit_default.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_right_activated.9.png b/res/drawable-mdpi/data_sweep_right_activated.9.png
new file mode 100644
index 0000000..5314538
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_right_activated.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_right_default.9.png b/res/drawable-mdpi/data_sweep_right_default.9.png
new file mode 100644
index 0000000..cc3b586
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_right_default.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_warning_activated.9.png b/res/drawable-mdpi/data_sweep_warning_activated.9.png
new file mode 100644
index 0000000..ed44d4d
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_warning_activated.9.png
Binary files differ
diff --git a/res/drawable-mdpi/data_sweep_warning_default.9.png b/res/drawable-mdpi/data_sweep_warning_default.9.png
new file mode 100644
index 0000000..760ea18
--- /dev/null
+++ b/res/drawable-mdpi/data_sweep_warning_default.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_settings_battery.png b/res/drawable-mdpi/ic_settings_battery.png
new file mode 100644
index 0000000..e1f478b
--- /dev/null
+++ b/res/drawable-mdpi/ic_settings_battery.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_settings_development.png b/res/drawable-mdpi/ic_settings_development.png
new file mode 100644
index 0000000..e1f478b
--- /dev/null
+++ b/res/drawable-mdpi/ic_settings_development.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_grid_border.9.png b/res/drawable-xhdpi/data_grid_border.9.png
new file mode 100644
index 0000000..2139cf2
--- /dev/null
+++ b/res/drawable-xhdpi/data_grid_border.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_grid_primary.9.png b/res/drawable-xhdpi/data_grid_primary.9.png
new file mode 100644
index 0000000..ae68886
--- /dev/null
+++ b/res/drawable-xhdpi/data_grid_primary.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_grid_secondary.9.png b/res/drawable-xhdpi/data_grid_secondary.9.png
new file mode 100644
index 0000000..7a09593
--- /dev/null
+++ b/res/drawable-xhdpi/data_grid_secondary.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_left_activated.9.png b/res/drawable-xhdpi/data_sweep_left_activated.9.png
new file mode 100644
index 0000000..ff9631e
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_left_activated.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_left_default.9.png b/res/drawable-xhdpi/data_sweep_left_default.9.png
new file mode 100644
index 0000000..2e0651c
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_left_default.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_limit_activated.9.png b/res/drawable-xhdpi/data_sweep_limit_activated.9.png
new file mode 100644
index 0000000..ae02388
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_limit_activated.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_limit_default.9.png b/res/drawable-xhdpi/data_sweep_limit_default.9.png
new file mode 100644
index 0000000..7391148
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_limit_default.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_right_activated.9.png b/res/drawable-xhdpi/data_sweep_right_activated.9.png
new file mode 100644
index 0000000..81c1a3c
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_right_activated.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_right_default.9.png b/res/drawable-xhdpi/data_sweep_right_default.9.png
new file mode 100644
index 0000000..94a9f61
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_right_default.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_warning_activated.9.png b/res/drawable-xhdpi/data_sweep_warning_activated.9.png
new file mode 100644
index 0000000..0a2d2b1
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_warning_activated.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/data_sweep_warning_default.9.png b/res/drawable-xhdpi/data_sweep_warning_default.9.png
new file mode 100644
index 0000000..d5f6044
--- /dev/null
+++ b/res/drawable-xhdpi/data_sweep_warning_default.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_settings_data_usage.png b/res/drawable-xhdpi/ic_settings_data_usage.png
new file mode 100644
index 0000000..176dd11
--- /dev/null
+++ b/res/drawable-xhdpi/ic_settings_data_usage.png
Binary files differ
diff --git a/res/drawable/data_sweep_left.xml b/res/drawable/data_sweep_left.xml
index 739a74e..cb801a0 100644
--- a/res/drawable/data_sweep_left.xml
+++ b/res/drawable/data_sweep_left.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
- <item android:state_activated="true" android:drawable="@drawable/data_sweep_left_activated" />
- <item android:state_activated="false" android:drawable="@drawable/data_sweep_left_default" />
+ <item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_left_activated" />
+ <item android:drawable="@drawable/data_sweep_left_default" />
</selector>
diff --git a/res/drawable/data_sweep_limit.xml b/res/drawable/data_sweep_limit.xml
index 29ecec8..378b0aa 100644
--- a/res/drawable/data_sweep_limit.xml
+++ b/res/drawable/data_sweep_limit.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
- <item android:state_activated="true" android:drawable="@drawable/data_sweep_limit_activated" />
- <item android:state_activated="false" android:drawable="@drawable/data_sweep_limit_default" />
+ <item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_limit_activated" />
+ <item android:drawable="@drawable/data_sweep_limit_default" />
</selector>
diff --git a/res/drawable/data_sweep_right.xml b/res/drawable/data_sweep_right.xml
index 1a11469..a75a1b2 100644
--- a/res/drawable/data_sweep_right.xml
+++ b/res/drawable/data_sweep_right.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
- <item android:state_activated="true" android:drawable="@drawable/data_sweep_right_activated" />
- <item android:state_activated="false" android:drawable="@drawable/data_sweep_right_default" />
+ <item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_right_activated" />
+ <item android:drawable="@drawable/data_sweep_right_default" />
</selector>
diff --git a/res/drawable/data_sweep_warning.xml b/res/drawable/data_sweep_warning.xml
index 5cafe06..001d0c5 100644
--- a/res/drawable/data_sweep_warning.xml
+++ b/res/drawable/data_sweep_warning.xml
@@ -17,6 +17,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
- <item android:state_activated="true" android:drawable="@drawable/data_sweep_warning_activated" />
- <item android:state_activated="false" android:drawable="@drawable/data_sweep_warning_default" />
+ <item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_warning_activated" />
+ <item android:drawable="@drawable/data_sweep_warning_default" />
</selector>
diff --git a/res/layout/data_usage_chart.xml b/res/layout/data_usage_chart.xml
index 5fd640f..199a38e 100644
--- a/res/layout/data_usage_chart.xml
+++ b/res/layout/data_usage_chart.xml
@@ -17,6 +17,7 @@
<com.android.settings.widget.DataUsageChartView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="220dip"
android:padding="16dip">
@@ -40,11 +41,19 @@
settings:fillColor="#c050ade5"
settings:fillColorSecondary="#88566abc" />
+ <com.android.settings.widget.ChartNetworkSeriesView
+ android:id="@+id/detail_series"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="left|bottom"
+ settings:strokeColor="#d88d3a"
+ settings:fillColor="#c0ba7f3e"
+ settings:fillColorSecondary="#0000" />
+
<com.android.settings.widget.ChartSweepView
android:id="@+id/sweep_left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_gravity="center_horizontal"
settings:sweepDrawable="@drawable/data_sweep_left"
settings:followAxis="horizontal"
settings:showLabel="false" />
@@ -53,7 +62,6 @@
android:id="@+id/sweep_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_gravity="center_horizontal"
settings:sweepDrawable="@drawable/data_sweep_right"
settings:followAxis="horizontal"
settings:showLabel="false" />
@@ -62,7 +70,6 @@
android:id="@+id/sweep_limit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
settings:sweepDrawable="@drawable/data_sweep_limit"
settings:followAxis="vertical"
settings:showLabel="true" />
@@ -71,7 +78,6 @@
android:id="@+id/sweep_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
settings:sweepDrawable="@drawable/data_sweep_warning"
settings:followAxis="vertical"
settings:showLabel="true" />
diff --git a/res/layout/data_usage_detail.xml b/res/layout/data_usage_detail.xml
index 9415b3f..2c8e490 100644
--- a/res/layout/data_usage_detail.xml
+++ b/res/layout/data_usage_detail.xml
@@ -14,43 +14,35 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/app_detail"
android:layout_width="match_parent"
- android:layout_height="match_parent">
- <LinearLayout
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/app_title"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip" />
- <FrameLayout
- android:id="@+id/chart_container"
- android:layout_width="match_parent"
- android:layout_height="233dip" />
+ <TextView
+ android:id="@+id/app_subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dip" />
- <TextView
- android:id="@android:id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dip" />
+ <Button
+ android:id="@+id/app_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dip"
+ android:text="@string/data_usage_app_settings" />
- <TextView
- android:id="@android:id/text1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dip" />
+ <LinearLayout
+ android:id="@+id/app_switches"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
- <Button
- android:id="@+id/data_usage_app_settings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="16dip"
- android:text="@string/data_usage_app_settings" />
-
- <LinearLayout
- android:id="@+id/switches"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" />
-
- </LinearLayout>
-</ScrollView>
+</LinearLayout>
diff --git a/res/layout/data_usage_header.xml b/res/layout/data_usage_header.xml
index 8e6f054..3f4ca5b 100644
--- a/res/layout/data_usage_header.xml
+++ b/res/layout/data_usage_header.xml
@@ -20,7 +20,7 @@
android:orientation="vertical">
<LinearLayout
- android:id="@+id/switches"
+ android:id="@+id/network_switches"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -48,4 +48,7 @@
</LinearLayout>
+ <include layout="@layout/data_usage_chart" />
+ <include layout="@layout/data_usage_detail" />
+
</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 24161c2..f7318bd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1330,7 +1330,7 @@
<!-- Main Settings screen setting option name to go into the sound settings screen -->
<string name="sound_settings_title">Sound</string>
<!-- Main Settings screen setting option name to go into the display settings screen -->
- <string name="display_settings_title">Screen</string>
+ <string name="display_settings_title">Display</string>
<!-- Sound settings screen heading -->
<string name="sound_settings">Sound settings</string>
<!-- Sound settings screen, setting option name checkbox -->
@@ -2677,7 +2677,7 @@
<skip />
<!-- Activity title for App Fuel Gauge summary -->
- <string name="power_usage_summary_title">Battery use</string>
+ <string name="power_usage_summary_title">Battery</string>
<!-- Activity title summary for App Fuel Gauge summary -->
<string name="power_usage_summary">What has been using the battery</string>
<!-- Message to show when battery usage data is not available [CHAR LIMIT=30] -->
@@ -3127,11 +3127,11 @@
<!-- Sound settings screen, setting option summary text -->
<string name="emergency_tone_summary">Set behavior when an emergency call is placed</string>
- <!-- Privacy Settings screen --><skip />
- <!-- Privacy settings menu title -->
- <string name="privacy_settings">Privacy</string>
+ <!-- Backup and reset Settings screen --><skip />
+ <!-- Backup and reset settings menu title -->
+ <string name="privacy_settings">Backup & reset</string>
<!-- Privacy settings activity title -->
- <string name="privacy_settings_title">Privacy settings</string>
+ <string name="privacy_settings_title">Backup & reset</string>
<!-- Backup section title -->
<string name="backup_section_title">Backup and restore</string>
<!-- Personal data section title -->
diff --git a/res/xml/application_settings.xml b/res/xml/application_settings.xml
index 3ad1e5d..3329662 100644
--- a/res/xml/application_settings.xml
+++ b/res/xml/application_settings.xml
@@ -14,6 +14,13 @@
limitations under the License.
-->
+<!--
+
+ This code is deprecated. This screen is no longer used in Settings.
+ The ApplicationSettings class is kept in case an external app references it directly.
+
+-->
+
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/applications_settings_header"
android:summary="@string/applications_settings_summary"
@@ -40,20 +47,6 @@
android:value="com.android.settings.Settings$StorageUseActivity" />
</PreferenceScreen>
- <PreferenceScreen
- android:key="power_usage"
- android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
- android:title="@string/power_usage_summary_title"
- android:summary="@string/power_usage_summary">
- </PreferenceScreen>
-
- <CheckBoxPreference
- android:key="toggle_install_applications"
- android:title="@string/install_applications"
- android:summaryOff="@string/install_unknown_applications"
- android:summaryOn="@string/install_unknown_applications"
- android:persistent="false" />
-
<CheckBoxPreference
android:key="toggle_advanced_settings"
android:title="@string/advanced_settings"
@@ -80,12 +73,5 @@
</PreferenceScreen>
-->
-
- <PreferenceScreen
- android:title="@string/development_settings_title"
- android:summary="@string/development_settings_summary"
- android:fragment="com.android.settings.DevelopmentSettings">
- </PreferenceScreen>
-
</PreferenceScreen>
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 95b2aca..e996f70 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -39,10 +39,19 @@
<PreferenceCategory android:title="@string/device_admin_title"
android:persistent="false">
+
<Preference android:title="@string/manage_device_admin"
android:summary="@string/manage_device_admin_summary"
android:persistent="false"
android:fragment="com.android.settings.DeviceAdminSettings"/>
+
+ <CheckBoxPreference
+ android:key="toggle_install_applications"
+ android:title="@string/install_applications"
+ android:summaryOff="@string/install_unknown_applications"
+ android:summaryOn="@string/install_unknown_applications"
+ android:persistent="false" />
+
</PreferenceCategory>
<PreferenceCategory android:title="@string/credentials_title"
diff --git a/res/xml/settings_headers.xml b/res/xml/settings_headers.xml
index 063d103..532bf7d 100644
--- a/res/xml/settings_headers.xml
+++ b/res/xml/settings_headers.xml
@@ -92,9 +92,16 @@
android:icon="@drawable/ic_settings_storage"
android:title="@string/storage_settings" />
+ <!-- Battery -->
+ <header
+ android:id="@+id/battery_settings"
+ android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
+ android:icon="@drawable/ic_settings_battery"
+ android:title="@string/power_usage_summary_title" />
+
<!-- Application Settings -->
<header
- android:fragment="com.android.settings.ApplicationSettings"
+ android:fragment="com.android.settings.applications.ManageApplications"
android:icon="@drawable/ic_settings_applications"
android:title="@string/applications_settings"
android:id="@+id/application_settings" />
@@ -133,13 +140,6 @@
android:title="@string/security_settings_title"
android:id="@+id/security_settings" />
- <!-- Privacy -->
- <header
- android:fragment="com.android.settings.PrivacySettings"
- android:icon="@drawable/ic_settings_privacy"
- android:title="@string/privacy_settings"
- android:id="@+id/privacy_settings" />
-
<!-- Language -->
<header
android:id="@+id/language_settings"
@@ -147,6 +147,13 @@
android:icon="@drawable/ic_settings_language"
android:title="@string/language_settings" />
+ <!-- Backup and reset -->
+ <header
+ android:fragment="com.android.settings.PrivacySettings"
+ android:icon="@drawable/ic_settings_privacy"
+ android:title="@string/privacy_settings"
+ android:id="@+id/privacy_settings" />
+
<!-- SYSTEM -->
<header android:title="@string/header_category_system" />
@@ -172,6 +179,13 @@
android:icon="@drawable/ic_settings_accessibility"
android:title="@string/accessibility_settings" />
+ <!-- Development -->
+ <header
+ android:id="@+id/development_settings"
+ android:fragment="com.android.settings.DevelopmentSettings"
+ android:icon="@drawable/ic_settings_development"
+ android:title="@string/development_settings_title" />
+
<!-- About Device -->
<header
android:id="@+id/about_settings"
diff --git a/src/com/android/settings/ApplicationSettings.java b/src/com/android/settings/ApplicationSettings.java
index 15eb840..27fc3ec 100644
--- a/src/com/android/settings/ApplicationSettings.java
+++ b/src/com/android/settings/ApplicationSettings.java
@@ -16,23 +16,17 @@
package com.android.settings;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.util.Log;
-public class ApplicationSettings extends SettingsPreferenceFragment implements
- DialogInterface.OnClickListener {
+public class ApplicationSettings extends SettingsPreferenceFragment {
- private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
private static final String KEY_TOGGLE_ADVANCED_SETTINGS = "toggle_advanced_settings";
private static final String KEY_APP_INSTALL_LOCATION = "app_install_location";
@@ -45,10 +39,8 @@
private static final String APP_INSTALL_SDCARD_ID = "sdcard";
private static final String APP_INSTALL_AUTO_ID = "auto";
- private CheckBoxPreference mToggleAppInstallation;
private CheckBoxPreference mToggleAdvancedSettings;
private ListPreference mInstallLocation;
- private DialogInterface mWarnInstallApps;
@Override
public void onCreate(Bundle icicle) {
@@ -56,10 +48,6 @@
addPreferencesFromResource(R.xml.application_settings);
- mToggleAppInstallation = (CheckBoxPreference)findPreference(
- KEY_TOGGLE_INSTALL_APPLICATIONS);
- mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
-
mToggleAdvancedSettings = (CheckBoxPreference)findPreference(
KEY_TOGGLE_ADVANCED_SETTINGS);
mToggleAdvancedSettings.setChecked(isAdvancedSettingsEnabled());
@@ -107,23 +95,8 @@
}
@Override
- public void onDestroy() {
- super.onDestroy();
- if (mWarnInstallApps != null) {
- mWarnInstallApps.dismiss();
- }
- }
-
- @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
- if (preference == mToggleAppInstallation) {
- if (mToggleAppInstallation.isChecked()) {
- mToggleAppInstallation.setChecked(false);
- warnAppInstallation();
- } else {
- setNonMarketAppsAllowed(false);
- }
- } else if (preference == mToggleAdvancedSettings) {
+ if (preference == mToggleAdvancedSettings) {
boolean value = mToggleAdvancedSettings.isChecked();
setAdvancedSettingsEnabled(value);
}
@@ -131,19 +104,6 @@
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
- public void onClick(DialogInterface dialog, int which) {
- if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) {
- setNonMarketAppsAllowed(true);
- mToggleAppInstallation.setChecked(true);
- }
- }
-
- private void setNonMarketAppsAllowed(boolean enabled) {
- // Change the system setting
- Settings.Secure.putInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS,
- enabled ? 1 : 0);
- }
-
private boolean isAdvancedSettingsEnabled() {
return Settings.System.getInt(getContentResolver(),
Settings.System.ADVANCED_SETTINGS,
@@ -160,11 +120,6 @@
getActivity().sendBroadcast(intent);
}
- private boolean isNonMarketAppsAllowed() {
- return Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.INSTALL_NON_MARKET_APPS, 0) > 0;
- }
-
private String getAppInstallLocation() {
int selectedLocation = Settings.System.getInt(getContentResolver(),
Settings.Secure.DEFAULT_INSTALL_LOCATION, APP_INSTALL_AUTO);
@@ -179,15 +134,4 @@
return APP_INSTALL_AUTO_ID;
}
}
-
- private void warnAppInstallation() {
- // TODO: DialogFragment?
- mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
- getResources().getString(R.string.error_title))
- .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
- .setMessage(getResources().getString(R.string.install_all_warning))
- .setPositiveButton(android.R.string.yes, this)
- .setNegativeButton(android.R.string.no, null)
- .show();
- }
}
diff --git a/src/com/android/settings/DataUsageAppDetail.java b/src/com/android/settings/DataUsageAppDetail.java
deleted file mode 100644
index 6294ad3..0000000
--- a/src/com/android/settings/DataUsageAppDetail.java
+++ /dev/null
@@ -1,309 +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.settings;
-
-import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static com.android.settings.DataUsageSummary.getHistoryBounds;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.Fragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.Color;
-import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
-import android.net.NetworkPolicyManager;
-import android.net.NetworkStats;
-import android.net.NetworkStatsHistory;
-import android.net.NetworkTemplate;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.preference.CheckBoxPreference;
-import android.preference.Preference;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.settings.widget.DataUsageChartView;
-import com.android.settings.widget.DataUsageChartView.DataUsageChartListener;
-
-public class DataUsageAppDetail extends Fragment {
- private static final String TAG = "DataUsage";
- private static final boolean LOGD = true;
-
- public static final String EXTRA_UID = "uid";
- public static final String EXTRA_NETWORK_TEMPLATE = "networkTemplate";
-
- private int mUid;
- private NetworkTemplate mTemplate;
-
- private Intent mAppSettingsIntent;
-
- private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
-
- private INetworkStatsService mStatsService;
- private INetworkPolicyManager mPolicyService;
-
- private CheckBoxPreference mRestrictBackground;
- private View mRestrictBackgroundView;
-
- private FrameLayout mChartContainer;
- private TextView mTitle;
- private TextView mText1;
- private Button mAppSettings;
- private LinearLayout mSwitches;
-
- private DataUsageChartView mChart;
- private NetworkStatsHistory mHistory;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- mPolicyService = INetworkPolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
- final Context context = inflater.getContext();
- final View view = inflater.inflate(R.layout.data_usage_detail, container, false);
-
- mChartContainer = (FrameLayout) view.findViewById(R.id.chart_container);
- mTitle = (TextView) view.findViewById(android.R.id.title);
- mText1 = (TextView) view.findViewById(android.R.id.text1);
- mAppSettings = (Button) view.findViewById(R.id.data_usage_app_settings);
- mSwitches = (LinearLayout) view.findViewById(R.id.switches);
-
- mRestrictBackground = new CheckBoxPreference(context);
- mRestrictBackground.setTitle(R.string.data_usage_app_restrict_background);
- mRestrictBackground.setSummary(R.string.data_usage_app_restrict_background_summary);
-
- // kick refresh once to force-create views
- refreshPreferenceViews();
-
- mSwitches.addView(mRestrictBackgroundView);
- mRestrictBackgroundView.setOnClickListener(mRestrictBackgroundListener);
-
- mAppSettings.setOnClickListener(mAppSettingsListener);
-
- mChart = new DataUsageChartView(context);
- mChartContainer.addView(mChart);
-
- mChart.setListener(mChartListener);
- mChart.setChartColor(Color.parseColor("#d88d3a"), Color.parseColor("#c0ba7f3e"),
- Color.parseColor("#88566abc"));
-
- return view;
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- updateBody();
- }
-
- private void updateBody() {
- final PackageManager pm = getActivity().getPackageManager();
-
- mUid = getArguments().getInt(EXTRA_UID);
- mTemplate = getArguments().getParcelable(EXTRA_NETWORK_TEMPLATE);
-
- mTitle.setText(pm.getNameForUid(mUid));
-
- // enable settings button when package provides it
- // TODO: target torwards entire UID instead of just first package
- final String[] packageNames = pm.getPackagesForUid(mUid);
- if (packageNames != null && packageNames.length > 0) {
- mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
- mAppSettingsIntent.setPackage(packageNames[0]);
- mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
-
- final boolean matchFound = pm.resolveActivity(mAppSettingsIntent, 0) != null;
- mAppSettings.setEnabled(matchFound);
-
- } else {
- mAppSettingsIntent = null;
- mAppSettings.setEnabled(false);
- }
-
- try {
- // load stats for current uid and template
- // TODO: read template from extras
- mHistory = mStatsService.getHistoryForUid(mTemplate, mUid, NetworkStats.TAG_NONE);
- } catch (RemoteException e) {
- // since we can't do much without history, and we don't want to
- // leave with half-baked UI, we bail hard.
- throw new RuntimeException("problem reading network stats", e);
- }
-
- // bind chart to historical stats
- mChart.bindNetworkStats(mHistory);
-
- // show entire history known
- final long[] bounds = getHistoryBounds(mHistory);
- mChart.setVisibleRange(bounds[0], bounds[1] + DateUtils.WEEK_IN_MILLIS, bounds[1]);
- updateDetailData();
-
- final Context context = getActivity();
- if (NetworkPolicyManager.isUidValidForPolicy(context, mUid)) {
- mRestrictBackgroundView.setVisibility(View.VISIBLE);
-
- final int uidPolicy;
- try {
- uidPolicy = mPolicyService.getUidPolicy(mUid);
- } catch (RemoteException e) {
- // since we can't do much without policy, we bail hard.
- throw new RuntimeException("problem reading network policy", e);
- }
-
- // update policy checkbox
- final boolean restrictBackground = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- mRestrictBackground.setChecked(restrictBackground);
-
- // kick preference views so they rebind from changes above
- refreshPreferenceViews();
-
- } else {
- mRestrictBackgroundView.setVisibility(View.GONE);
- }
- }
-
- private void updateDetailData() {
- if (LOGD) Log.d(TAG, "updateDetailData()");
-
- final Context context = mChart.getContext();
- final long[] range = mChart.getInspectRange();
- final long[] total = mHistory.getTotalData(range[0], range[1], null);
- final long totalCombined = total[0] + total[1];
- mText1.setText(Formatter.formatFileSize(context, totalCombined));
- }
-
- private void setRestrictBackground(boolean restrictBackground) {
- if (LOGD) Log.d(TAG, "setRestrictBackground()");
- try {
- mPolicyService.setUidPolicy(
- mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
- } catch (RemoteException e) {
- throw new RuntimeException("unable to save policy", e);
- }
-
- mRestrictBackground.setChecked(restrictBackground);
- refreshPreferenceViews();
- }
-
- /**
- * Force rebind of hijacked {@link Preference} views.
- */
- private void refreshPreferenceViews() {
- mRestrictBackgroundView = mRestrictBackground.getView(mRestrictBackgroundView, mSwitches);
- }
-
- private DataUsageChartListener mChartListener = new DataUsageChartListener() {
- /** {@inheritDoc} */
- public void onInspectRangeChanged() {
- if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
- updateDetailData();
- }
-
- /** {@inheritDoc} */
- public void onWarningChanged() {
- // ignored
- }
-
- /** {@inheritDoc} */
- public void onLimitChanged() {
- // ignored
- }
- };
-
- private OnClickListener mAppSettingsListener = new OnClickListener() {
- /** {@inheritDoc} */
- public void onClick(View v) {
- // TODO: target torwards entire UID instead of just first package
- startActivity(mAppSettingsIntent);
- }
- };
-
- private OnClickListener mRestrictBackgroundListener = new OnClickListener() {
- /** {@inheritDoc} */
- public void onClick(View v) {
- final boolean restrictBackground = !mRestrictBackground.isChecked();
-
- if (restrictBackground) {
- // enabling restriction; show confirmation dialog which
- // eventually calls setRestrictBackground() once user confirms.
- ConfirmRestrictFragment.show(DataUsageAppDetail.this);
- } else {
- setRestrictBackground(false);
- }
- }
- };
-
- /**
- * Dialog to request user confirmation before setting
- * {@link #POLICY_REJECT_METERED_BACKGROUND}.
- */
- public static class ConfirmRestrictFragment extends DialogFragment {
- public static void show(DataUsageAppDetail parent) {
- final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment();
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.data_usage_app_restrict_dialog_title);
- builder.setMessage(R.string.data_usage_app_restrict_dialog);
-
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- final DataUsageAppDetail target = (DataUsageAppDetail) getTargetFragment();
- if (target != null) {
- target.setRestrictBackground(true);
- }
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
-
- return builder.create();
- }
- }
-
-}
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index 692c753..098f57a 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -21,6 +21,8 @@
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
@@ -29,10 +31,12 @@
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import android.animation.LayoutTransition;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
+import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -54,7 +58,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -66,12 +69,14 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -106,8 +111,6 @@
private static final String TAG = "DataUsage";
private static final boolean LOGD = true;
- private static final int TEMPLATE_INVALID = -1;
-
private static final String TAB_3G = "3g";
private static final String TAB_4G = "4g";
private static final String TAB_MOBILE = "mobile";
@@ -116,6 +119,8 @@
private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
private static final String TAG_CYCLE_EDITOR = "cycleEditor";
private static final String TAG_POLICY_LIMIT = "policyLimit";
+ private static final String TAG_CONFIRM_RESTRICT = "confirmRestrict";
+ private static final String TAG_APP_DETAILS = "appDetails";
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
@@ -135,25 +140,41 @@
private ListView mListView;
private DataUsageAdapter mAdapter;
- private View mHeader;
- private LinearLayout mSwitches;
+ private ViewGroup mHeader;
+ private LinearLayout mNetworkSwitches;
private Switch mDataEnabled;
- private CheckBox mDisableAtLimit;
private View mDataEnabledView;
+ private CheckBox mDisableAtLimit;
private View mDisableAtLimitView;
- private DataUsageChartView mChart;
-
private Spinner mCycleSpinner;
private CycleAdapter mCycleAdapter;
+ private DataUsageChartView mChart;
+
+ private View mAppDetail;
+ private TextView mAppTitle;
+ private TextView mAppSubtitle;
+ private Button mAppSettings;
+
+ private LinearLayout mAppSwitches;
+ private CheckBox mAppRestrict;
+ private View mAppRestrictView;
+
private boolean mShowWifi = false;
private NetworkTemplate mTemplate = null;
+ private static final int UID_NONE = -1;
+ private int mUid = UID_NONE;
+
+ private Intent mAppSettingsIntent;
+
private NetworkPolicyEditor mPolicyEditor;
+
private NetworkStatsHistory mHistory;
+ private NetworkStatsHistory mDetailHistory;
private String mIntentTab = null;
@@ -194,30 +215,57 @@
mTabHost.setup();
mTabHost.setOnTabChangedListener(mTabListener);
- mHeader = inflater.inflate(R.layout.data_usage_header, mListView, false);
+ mHeader = (ViewGroup) inflater.inflate(R.layout.data_usage_header, mListView, false);
mListView.addHeaderView(mHeader, null, false);
- mDataEnabled = new Switch(inflater.getContext());
- mDataEnabledView = inflatePreference(inflater, mSwitches, mDataEnabled);
- mDataEnabled.setOnCheckedChangeListener(mDataEnabledListener);
+ {
+ // bind network switches
+ mNetworkSwitches = (LinearLayout) mHeader.findViewById(R.id.network_switches);
- mDisableAtLimit = new CheckBox(inflater.getContext());
- mDisableAtLimit.setClickable(false);
- mDisableAtLimitView = inflatePreference(inflater, mSwitches, mDisableAtLimit);
- mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
+ mDataEnabled = new Switch(inflater.getContext());
+ mDataEnabledView = inflatePreference(inflater, mNetworkSwitches, mDataEnabled);
+ mDataEnabled.setOnCheckedChangeListener(mDataEnabledListener);
+ mNetworkSwitches.addView(mDataEnabledView);
- mSwitches = (LinearLayout) mHeader.findViewById(R.id.switches);
- mSwitches.addView(mDataEnabledView);
- mSwitches.addView(mDisableAtLimitView);
+ mDisableAtLimit = new CheckBox(inflater.getContext());
+ mDisableAtLimit.setClickable(false);
+ mDisableAtLimitView = inflatePreference(inflater, mNetworkSwitches, mDisableAtLimit);
+ mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
+ mNetworkSwitches.addView(mDisableAtLimitView);
+ }
+ // bind cycle dropdown
mCycleSpinner = (Spinner) mHeader.findViewById(R.id.cycles);
mCycleAdapter = new CycleAdapter(context);
mCycleSpinner.setAdapter(mCycleAdapter);
mCycleSpinner.setOnItemSelectedListener(mCycleListener);
- mChart = (DataUsageChartView) inflater.inflate(R.layout.data_usage_chart, mListView, false);
+ mChart = (DataUsageChartView) mHeader.findViewById(R.id.chart);
mChart.setListener(mChartListener);
- mListView.addHeaderView(mChart, null, false);
+
+ {
+ // bind app detail controls
+ mAppDetail = view.findViewById(R.id.app_detail);
+ mAppTitle = (TextView) view.findViewById(R.id.app_title);
+ mAppSubtitle = (TextView) view.findViewById(R.id.app_subtitle);
+ mAppSwitches = (LinearLayout) view.findViewById(R.id.app_switches);
+
+ mAppSettings = (Button) view.findViewById(R.id.app_settings);
+ mAppSettings.setOnClickListener(mAppSettingsListener);
+
+ mAppRestrict = new CheckBox(inflater.getContext());
+ mAppRestrict.setClickable(false);
+ mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict);
+ setPreferenceTitle(mAppRestrictView, R.string.data_usage_app_restrict_background);
+ setPreferenceSummary(
+ mAppRestrictView, R.string.data_usage_app_restrict_background_summary);
+ mAppRestrictView.setOnClickListener(mAppRestrictListener);
+ mAppSwitches.addView(mAppRestrictView);
+ }
+
+ // TODO: tweak these transitions
+ final LayoutTransition transition = new LayoutTransition();
+ mHeader.setLayoutTransition(transition);
mAdapter = new DataUsageAdapter();
mListView.setOnItemClickListener(mListListener);
@@ -433,6 +481,7 @@
mChart.bindNetworkStats(mHistory);
updatePolicy(true);
+ updateAppDetail();
// force scroll to top of body
mListView.smoothScrollToPosition(0);
@@ -440,6 +489,84 @@
mBinding = false;
}
+ private boolean isAppDetailMode() {
+ return mUid != UID_NONE;
+ }
+
+ /**
+ * Update UID details panels to match {@link #mUid}, showing or hiding them
+ * depending on {@link #isAppDetailMode()}.
+ */
+ private void updateAppDetail() {
+ if (isAppDetailMode()) {
+ mAppDetail.setVisibility(View.VISIBLE);
+ } else {
+ mAppDetail.setVisibility(View.GONE);
+
+ // hide detail stats when not in detail mode
+ mChart.bindDetailNetworkStats(null);
+ return;
+ }
+
+ // remove warning/limit sweeps while in detail mode
+ mChart.bindNetworkPolicy(null);
+
+ final PackageManager pm = getActivity().getPackageManager();
+ mAppTitle.setText(pm.getNameForUid(mUid));
+
+ // enable settings button when package provides it
+ // TODO: target torwards entire UID instead of just first package
+ final String[] packageNames = pm.getPackagesForUid(mUid);
+ if (packageNames != null && packageNames.length > 0) {
+ mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
+ mAppSettingsIntent.setPackage(packageNames[0]);
+ mAppSettingsIntent.addCategory(Intent.CATEGORY_DEFAULT);
+
+ final boolean matchFound = pm.resolveActivity(mAppSettingsIntent, 0) != null;
+ mAppSettings.setEnabled(matchFound);
+
+ } else {
+ mAppSettingsIntent = null;
+ mAppSettings.setEnabled(false);
+ }
+
+ try {
+ // load stats for current uid and template
+ // TODO: read template from extras
+ mDetailHistory = mStatsService.getHistoryForUid(mTemplate, mUid, NetworkStats.TAG_NONE);
+ } catch (RemoteException e) {
+ // since we can't do much without history, and we don't want to
+ // leave with half-baked UI, we bail hard.
+ throw new RuntimeException("problem reading network stats", e);
+ }
+
+ // bind chart to historical stats
+ mChart.bindDetailNetworkStats(mDetailHistory);
+
+ updateDetailData();
+
+ final Context context = getActivity();
+ if (NetworkPolicyManager.isUidValidForPolicy(context, mUid)) {
+ mAppRestrictView.setVisibility(View.VISIBLE);
+
+ final int uidPolicy;
+ try {
+ uidPolicy = mPolicyService.getUidPolicy(mUid);
+ } catch (RemoteException e) {
+ // since we can't do much without policy, we bail hard.
+ throw new RuntimeException("problem reading network policy", e);
+ }
+
+ // update policy checkbox
+ final boolean restrictBackground = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ mAppRestrict.setChecked(restrictBackground);
+
+ } else {
+ mAppRestrictView.setVisibility(View.GONE);
+ }
+
+ }
+
private void setPolicyCycleDay(int cycleDay) {
if (LOGD) Log.d(TAG, "setPolicyCycleDay()");
mPolicyEditor.setPolicyCycleDay(mTemplate, cycleDay);
@@ -458,11 +585,30 @@
updatePolicy(false);
}
+ private void setAppRestrictBackground(boolean restrictBackground) {
+ if (LOGD) Log.d(TAG, "setRestrictBackground()");
+ try {
+ mPolicyService.setUidPolicy(
+ mUid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
+ } catch (RemoteException e) {
+ throw new RuntimeException("unable to save policy", e);
+ }
+
+ mAppRestrict.setChecked(restrictBackground);
+ }
+
/**
* Update chart sweeps and cycle list to reflect {@link NetworkPolicy} for
* current {@link #mTemplate}.
*/
private void updatePolicy(boolean refreshCycle) {
+ if (isAppDetailMode()) {
+ mNetworkSwitches.setVisibility(View.GONE);
+ // we fall through to update cycle list for detail mode
+ } else {
+ mNetworkSwitches.setVisibility(View.VISIBLE);
+ }
+
final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
// reflect policy limit in checkbox
@@ -572,18 +718,34 @@
}
};
+ private View.OnClickListener mAppRestrictListener = new View.OnClickListener() {
+ /** {@inheritDoc} */
+ public void onClick(View v) {
+ final boolean restrictBackground = !mAppRestrict.isChecked();
+
+ if (restrictBackground) {
+ // enabling restriction; show confirmation dialog which
+ // eventually calls setRestrictBackground() once user confirms.
+ ConfirmRestrictFragment.show(DataUsageSummary.this);
+ } else {
+ setAppRestrictBackground(false);
+ }
+ }
+ };
+
+ private OnClickListener mAppSettingsListener = new OnClickListener() {
+ /** {@inheritDoc} */
+ public void onClick(View v) {
+ // TODO: target torwards entire UID instead of just first package
+ startActivity(mAppSettingsIntent);
+ }
+ };
+
private OnItemClickListener mListListener = new OnItemClickListener() {
/** {@inheritDoc} */
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final AppUsageItem app = (AppUsageItem) parent.getItemAtPosition(position);
-
- final Bundle args = new Bundle();
- args.putParcelable(DataUsageAppDetail.EXTRA_NETWORK_TEMPLATE, mTemplate);
- args.putInt(DataUsageAppDetail.EXTRA_UID, app.uid);
-
- final PreferenceActivity activity = (PreferenceActivity) getActivity();
- activity.startPreferencePanel(DataUsageAppDetail.class.getName(), args,
- R.string.data_usage_summary_title, null, null, 0);
+ AppDetailsFragment.show(DataUsageSummary.this, app.uid);
}
};
@@ -621,12 +783,30 @@
};
/**
- * Update {@link #mAdapter} with sorted list of applications data usage,
- * based on current inspection from {@link #mChart}.
+ * Update details based on {@link #mChart} inspection range depending on
+ * current mode. In network mode, updates {@link #mAdapter} with sorted list
+ * of applications data usage, and when {@link #isAppDetailMode()} update
+ * app details.
*/
private void updateDetailData() {
if (LOGD) Log.d(TAG, "updateDetailData()");
+ if (isAppDetailMode()) {
+ if (mDetailHistory != null) {
+ final Context context = mChart.getContext();
+ final long[] range = mChart.getInspectRange();
+ final long[] total = mDetailHistory.getTotalData(range[0], range[1], null);
+ final long totalCombined = total[0] + total[1];
+ mAppSubtitle.setText(Formatter.formatFileSize(context, totalCombined));
+ }
+
+ // clear any existing app list details
+ mAdapter.bindStats(null);
+
+ return;
+ }
+
+ // otherwise kick off task to update list
new AsyncTask<Void, Void, NetworkStats>() {
@Override
protected NetworkStats doInBackground(Void... params) {
@@ -753,15 +933,20 @@
public static class DataUsageAdapter extends BaseAdapter {
private ArrayList<AppUsageItem> mItems = Lists.newArrayList();
+ /**
+ * Bind the given {@link NetworkStats}, or {@code null} to clear list.
+ */
public void bindStats(NetworkStats stats) {
mItems.clear();
- for (int i = 0; i < stats.size; i++) {
- final long total = stats.rx[i] + stats.tx[i];
- final AppUsageItem item = new AppUsageItem();
- item.uid = stats.uid[i];
- item.total = total;
- mItems.add(item);
+ if (stats != null) {
+ for (int i = 0; i < stats.size; i++) {
+ final long total = stats.rx[i] + stats.tx[i];
+ final AppUsageItem item = new AppUsageItem();
+ item.uid = stats.uid[i];
+ item.total = total;
+ mItems.add(item);
+ }
}
Collections.sort(mItems);
@@ -806,6 +991,44 @@
}
/**
+ * Empty {@link Fragment} that controls display of UID details in
+ * {@link DataUsageSummary}.
+ */
+ public static class AppDetailsFragment extends Fragment {
+ public static final String EXTRA_UID = "uid";
+
+ public static void show(DataUsageSummary parent, int uid) {
+ final Bundle args = new Bundle();
+ args.putInt(EXTRA_UID, uid);
+
+ final AppDetailsFragment fragment = new AppDetailsFragment();
+ fragment.setArguments(args);
+ fragment.setTargetFragment(parent, 0);
+
+ final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
+ ft.add(fragment, TAG_APP_DETAILS);
+ ft.addToBackStack(TAG_APP_DETAILS);
+ ft.commit();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
+ target.mUid = getArguments().getInt(EXTRA_UID);
+ target.updateBody();
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
+ target.mUid = UID_NONE;
+ target.updateBody();
+ }
+ }
+
+ /**
* Dialog to request user confirmation before setting
* {@link NetworkPolicy#limitBytes}.
*/
@@ -976,11 +1199,44 @@
}
/**
+ * Dialog to request user confirmation before setting
+ * {@link #POLICY_REJECT_METERED_BACKGROUND}.
+ */
+ public static class ConfirmRestrictFragment extends DialogFragment {
+ public static void show(DataUsageSummary parent) {
+ final ConfirmRestrictFragment dialog = new ConfirmRestrictFragment();
+ dialog.setTargetFragment(parent, 0);
+ dialog.show(parent.getFragmentManager(), TAG_CONFIRM_RESTRICT);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Context context = getActivity();
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.data_usage_app_restrict_dialog_title);
+ builder.setMessage(R.string.data_usage_app_restrict_dialog);
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
+ if (target != null) {
+ target.setAppRestrictBackground(true);
+ }
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, null);
+
+ return builder.create();
+ }
+ }
+
+ /**
* Compute default tab that should be selected, based on
* {@link NetworkPolicyManager#EXTRA_NETWORK_TEMPLATE} extra.
*/
private static String computeTabFromIntent(Intent intent) {
- final int networkTemplate = intent.getIntExtra(EXTRA_NETWORK_TEMPLATE, TEMPLATE_INVALID);
+ final int networkTemplate = intent.getIntExtra(EXTRA_NETWORK_TEMPLATE, MATCH_MOBILE_ALL);
switch (networkTemplate) {
case MATCH_MOBILE_3G_LOWER:
return TAB_3G;
@@ -1083,4 +1339,14 @@
title.setText(resId);
}
+ /**
+ * Set {@link android.R.id#summary} for a preference view inflated with
+ * {@link #inflatePreference(LayoutInflater, ViewGroup, View)}.
+ */
+ private static void setPreferenceSummary(View parent, int resId) {
+ final TextView summary = (TextView) parent.findViewById(android.R.id.summary);
+ summary.setVisibility(View.VISIBLE);
+ summary.setText(resId);
+ }
+
}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index fc91e78..057e5de 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -19,8 +19,10 @@
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
@@ -43,7 +45,7 @@
* Gesture lock pattern settings.
*/
public class SecuritySettings extends SettingsPreferenceFragment
- implements OnPreferenceChangeListener {
+ implements OnPreferenceChangeListener, DialogInterface.OnClickListener {
// Lock Settings
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
@@ -58,6 +60,7 @@
private static final String KEY_SIM_LOCK = "sim_lock";
private static final String KEY_SHOW_PASSWORD = "show_password";
private static final String KEY_RESET_CREDENTIALS = "reset_credentials";
+ private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
DevicePolicyManager mDPM;
@@ -72,6 +75,9 @@
private Preference mResetCredentials;
+ private CheckBoxPreference mToggleAppInstallation;
+ private DialogInterface mWarnInstallApps;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -167,9 +173,50 @@
// Credential storage
mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
+ mToggleAppInstallation = (CheckBoxPreference) findPreference(
+ KEY_TOGGLE_INSTALL_APPLICATIONS);
+ mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
+
return root;
}
+ private boolean isNonMarketAppsAllowed() {
+ return Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.INSTALL_NON_MARKET_APPS, 0) > 0;
+ }
+
+ private void setNonMarketAppsAllowed(boolean enabled) {
+ // Change the system setting
+ Settings.Secure.putInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS,
+ enabled ? 1 : 0);
+ }
+
+ private void warnAppInstallation() {
+ // TODO: DialogFragment?
+ mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
+ getResources().getString(R.string.error_title))
+ .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
+ .setMessage(getResources().getString(R.string.install_all_warning))
+ .setPositiveButton(android.R.string.yes, this)
+ .setNegativeButton(android.R.string.no, null)
+ .show();
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) {
+ setNonMarketAppsAllowed(true);
+ mToggleAppInstallation.setChecked(true);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mWarnInstallApps != null) {
+ mWarnInstallApps.dismiss();
+ }
+ }
+
private void setupLockAfterPreference() {
// Compatible with pre-Froyo
long currentTimeout = Settings.Secure.getLong(getContentResolver(),
@@ -272,6 +319,13 @@
} else if (preference == mShowPassword) {
Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
mShowPassword.isChecked() ? 1 : 0);
+ } else if (preference == mToggleAppInstallation) {
+ if (mToggleAppInstallation.isChecked()) {
+ mToggleAppInstallation.setChecked(false);
+ warnAppInstallation();
+ } else {
+ setNonMarketAppsAllowed(false);
+ }
} else {
// If we didn't handle it, let preferences handle it.
return super.onPreferenceTreeClick(preferenceScreen, preference);
diff --git a/src/com/android/settings/net/NetworkPolicyEditor.java b/src/com/android/settings/net/NetworkPolicyEditor.java
index c50a490..61c2550 100644
--- a/src/com/android/settings/net/NetworkPolicyEditor.java
+++ b/src/com/android/settings/net/NetworkPolicyEditor.java
@@ -16,6 +16,8 @@
package com.android.settings.net;
+import static android.net.NetworkPolicy.LIMIT_DISABLED;
+import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
@@ -51,6 +53,14 @@
final NetworkPolicy[] policies = mPolicyService.getNetworkPolicies();
mPolicies.clear();
for (NetworkPolicy policy : policies) {
+ // TODO: find better place to clamp these
+ if (policy.limitBytes < -1) {
+ policy.limitBytes = LIMIT_DISABLED;
+ }
+ if (policy.warningBytes < -1) {
+ policy.warningBytes = WARNING_DISABLED;
+ }
+
mPolicies.add(policy);
}
} catch (RemoteException e) {
diff --git a/src/com/android/settings/widget/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java
index 0a34565..83c10cd 100644
--- a/src/com/android/settings/widget/ChartNetworkSeriesView.java
+++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java
@@ -75,6 +75,7 @@
R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
setChartColor(stroke, fill, fillSecondary);
+ setWillNotDraw(false);
a.recycle();
@@ -110,8 +111,13 @@
mPathStroke.reset();
mPathFill.reset();
+ invalidate();
}
+ /**
+ * Set the range to paint with {@link #mPaintFill}, leaving the remaining
+ * area to be painted with {@link #mPaintFillSecondary}.
+ */
public void setPrimaryRange(long left, long right) {
mPrimaryLeft = left;
mPrimaryRight = right;
@@ -190,18 +196,21 @@
protected void onDraw(Canvas canvas) {
int save;
+ final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
+ final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);
+
save = canvas.save();
- canvas.clipRect(0, 0, mPrimaryLeft, getHeight());
+ canvas.clipRect(0, 0, primaryLeftPoint, getHeight());
canvas.drawPath(mPathFill, mPaintFillSecondary);
canvas.restoreToCount(save);
save = canvas.save();
- canvas.clipRect(mPrimaryRight, 0, getWidth(), getHeight());
+ canvas.clipRect(primaryRightPoint, 0, getWidth(), getHeight());
canvas.drawPath(mPathFill, mPaintFillSecondary);
canvas.restoreToCount(save);
save = canvas.save();
- canvas.clipRect(mPrimaryLeft, 0, mPrimaryRight, getHeight());
+ canvas.clipRect(primaryLeftPoint, 0, primaryRightPoint, getHeight());
canvas.drawPath(mPathFill, mPaintFill);
canvas.drawPath(mPathStroke, mPaintStroke);
canvas.restoreToCount(save);
diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java
index 881fde4..d8344d5 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -39,6 +39,8 @@
// TODO: paint label when requested
private Drawable mSweep;
+ private Rect mSweepMargins = new Rect();
+
private int mFollowAxis;
private boolean mShowLabel;
@@ -88,8 +90,28 @@
return mFollowAxis;
}
- public void getExtraMargins(Rect rect) {
- mSweep.getPadding(rect);
+ /**
+ * Return margins of {@link #setSweepDrawable(Drawable)}, indicating how the
+ * sweep should be displayed around a content region.
+ */
+ public Rect getSweepMargins() {
+ return mSweepMargins;
+ }
+
+ /**
+ * Return the number of pixels that the "target" area is inset from the
+ * {@link View} edge, along the current {@link #setFollowAxis(int)}.
+ */
+ public float getTargetInset() {
+ if (mFollowAxis == VERTICAL) {
+ final float targetHeight = mSweep.getIntrinsicHeight() - mSweepMargins.top
+ - mSweepMargins.bottom;
+ return mSweepMargins.top + (targetHeight / 2);
+ } else {
+ final float targetWidth = mSweep.getIntrinsicWidth() - mSweepMargins.left
+ - mSweepMargins.right;
+ return mSweepMargins.left + (targetWidth / 2);
+ }
}
public void addOnSweepListener(OnSweepListener listener) {
@@ -115,6 +137,7 @@
}
sweep.setVisible(getVisibility() == VISIBLE, false);
mSweep = sweep;
+ sweep.getPadding(mSweepMargins);
} else {
mSweep = null;
}
@@ -175,33 +198,51 @@
final View parent = (View) getParent();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
- mTracking = event.copy();
- return true;
+
+ // only start tracking when in sweet spot
+ final boolean accept;
+ if (mFollowAxis == VERTICAL) {
+ accept = event.getX() > getWidth() - (mSweepMargins.right * 2);
+ } else {
+ accept = event.getY() > getHeight() - (mSweepMargins.bottom * 2);
+ }
+
+ if (accept) {
+ mTracking = event.copy();
+ return true;
+ } else {
+ return false;
+ }
}
case MotionEvent.ACTION_MOVE: {
getParent().requestDisallowInterceptTouchEvent(true);
+ final Rect sweepMargins = mSweepMargins;
+
+ // content area of parent
+ final Rect parentContent = new Rect(parent.getPaddingLeft(), parent.getPaddingTop(),
+ parent.getWidth() - parent.getPaddingRight(),
+ parent.getHeight() - parent.getPaddingBottom());
+
if (mFollowAxis == VERTICAL) {
- final float chartHeight = parent.getHeight() - parent.getPaddingTop()
- - parent.getPaddingBottom();
- final float translationY = MathUtils.constrain(
- event.getRawY() - mTracking.getRawY(), -getTop(),
- chartHeight - getTop());
- setTranslationY(translationY);
- final float point = (getTop() + getTranslationY() + (getHeight() / 2))
- - parent.getPaddingTop();
- mValue = mAxis.convertToValue(point);
+ final float currentTargetY = getTop() + getTargetInset();
+ final float requestedTargetY = currentTargetY
+ + (event.getRawY() - mTracking.getRawY());
+ final float clampedTargetY = MathUtils.constrain(
+ requestedTargetY, parentContent.top, parentContent.bottom);
+ setTranslationY(clampedTargetY - currentTargetY);
+
+ mValue = mAxis.convertToValue(clampedTargetY - parentContent.top);
dispatchOnSweep(false);
} else {
- final float chartWidth = parent.getWidth() - parent.getPaddingLeft()
- - parent.getPaddingRight();
- final float translationX = MathUtils.constrain(
- event.getRawX() - mTracking.getRawX(), -getLeft(),
- chartWidth - getLeft());
- setTranslationX(translationX);
- final float point = (getLeft() + getTranslationX() + (getWidth() / 2))
- - parent.getPaddingLeft();
- mValue = mAxis.convertToValue(point);
+ final float currentTargetX = getLeft() + getTargetInset();
+ final float requestedTargetX = currentTargetX
+ + (event.getRawX() - mTracking.getRawX());
+ final float clampedTargetX = MathUtils.constrain(
+ requestedTargetX, parentContent.left, parentContent.right);
+ setTranslationX(clampedTargetX - currentTargetX);
+
+ mValue = mAxis.convertToValue(clampedTargetX - parentContent.left);
dispatchOnSweep(false);
}
return true;
diff --git a/src/com/android/settings/widget/ChartView.java b/src/com/android/settings/widget/ChartView.java
index d762631..bf5616d 100644
--- a/src/com/android/settings/widget/ChartView.java
+++ b/src/com/android/settings/widget/ChartView.java
@@ -36,6 +36,8 @@
// TODO: extend something that supports two-dimensional scrolling
+ private static final int SWEEP_GRAVITY = Gravity.TOP | Gravity.LEFT;
+
ChartAxis mHoriz;
ChartAxis mVert;
@@ -74,7 +76,6 @@
final Rect parentRect = new Rect();
final Rect childRect = new Rect();
- final Rect extraMargins = new Rect();
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
@@ -91,21 +92,23 @@
} else if (child instanceof ChartSweepView) {
// sweep is always placed along specific dimension
final ChartSweepView sweep = (ChartSweepView) child;
+ final Rect sweepMargins = sweep.getSweepMargins();
final float point = sweep.getPoint();
- sweep.getExtraMargins(extraMargins);
if (sweep.getFollowAxis() == ChartSweepView.HORIZONTAL) {
- parentRect.left = parentRect.right = (int) point + getPaddingLeft();
- parentRect.top -= extraMargins.top;
- parentRect.bottom += extraMargins.bottom;
- Gravity.apply(params.gravity, child.getMeasuredWidth(), parentRect.height(),
+ parentRect.left = parentRect.right =
+ (int) (sweep.getPoint() - sweep.getTargetInset()) + getPaddingLeft();
+ parentRect.top -= sweepMargins.top;
+ parentRect.bottom += sweepMargins.bottom;
+ Gravity.apply(SWEEP_GRAVITY, child.getMeasuredWidth(), parentRect.height(),
parentRect, childRect);
} else {
- parentRect.top = parentRect.bottom = (int) point + getPaddingTop();
- parentRect.left -= extraMargins.left;
- parentRect.right += extraMargins.right;
- Gravity.apply(params.gravity, parentRect.width(), child.getMeasuredHeight(),
+ parentRect.top = parentRect.bottom =
+ (int) (sweep.getPoint() - sweep.getTargetInset()) + getPaddingTop();
+ parentRect.left -= sweepMargins.left;
+ parentRect.right += sweepMargins.right;
+ Gravity.apply(SWEEP_GRAVITY, parentRect.width(), child.getMeasuredHeight(),
parentRect, childRect);
}
}
diff --git a/src/com/android/settings/widget/DataUsageChartView.java b/src/com/android/settings/widget/DataUsageChartView.java
index 1c76291..6fe4042 100644
--- a/src/com/android/settings/widget/DataUsageChartView.java
+++ b/src/com/android/settings/widget/DataUsageChartView.java
@@ -38,10 +38,10 @@
private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
// TODO: enforce that sweeps cant cross each other
- // TODO: limit sweeps at graph boundaries
private ChartGridView mGrid;
private ChartNetworkSeriesView mSeries;
+ private ChartNetworkSeriesView mDetailSeries;
private ChartSweepView mSweepLeft;
private ChartSweepView mSweepRight;
@@ -75,6 +75,8 @@
mGrid = (ChartGridView) findViewById(R.id.grid);
mSeries = (ChartNetworkSeriesView) findViewById(R.id.series);
+ mDetailSeries = (ChartNetworkSeriesView) findViewById(R.id.detail_series);
+ mDetailSeries.setVisibility(View.GONE);
mSweepLeft = (ChartSweepView) findViewById(R.id.sweep_left);
mSweepRight = (ChartSweepView) findViewById(R.id.sweep_right);
@@ -89,6 +91,7 @@
// tell everyone about our axis
mGrid.init(mHoriz, mVert);
mSeries.init(mHoriz, mVert);
+ mDetailSeries.init(mHoriz, mVert);
mSweepLeft.init(mHoriz);
mSweepRight.init(mHoriz);
mSweepWarning.init(mVert);
@@ -97,27 +100,21 @@
setActivated(false);
}
- @Override
- public void setActivated(boolean activated) {
- super.setActivated(activated);
-
- mSweepLeft.setEnabled(activated);
- mSweepRight.setEnabled(activated);
- mSweepWarning.setEnabled(activated);
- mSweepLimit.setEnabled(activated);
- }
-
- @Deprecated
- public void setChartColor(int stroke, int fill, int disabled) {
- mSeries.setChartColor(stroke, fill, disabled);
- }
-
public void setListener(DataUsageChartListener listener) {
mListener = listener;
}
public void bindNetworkStats(NetworkStatsHistory stats) {
mSeries.bindNetworkStats(stats);
+ updatePrimaryRange();
+ requestLayout();
+ }
+
+ public void bindDetailNetworkStats(NetworkStatsHistory stats) {
+ mDetailSeries.bindNetworkStats(stats);
+ mDetailSeries.setVisibility(stats != null ? View.VISIBLE : View.GONE);
+ updatePrimaryRange();
+ requestLayout();
}
public void bindNetworkPolicy(NetworkPolicy policy) {
@@ -146,22 +143,11 @@
}
requestLayout();
-
- // TODO: eventually remove this; was to work around lack of sweep clamping
- if (policy.limitBytes < -1 || policy.limitBytes > 5 * GB_IN_BYTES) {
- policy.limitBytes = 5 * GB_IN_BYTES;
- mLimitListener.onSweep(mSweepLimit, true);
- }
- if (policy.warningBytes < -1 || policy.warningBytes > 5 * GB_IN_BYTES) {
- policy.warningBytes = 4 * GB_IN_BYTES;
- mWarningListener.onSweep(mSweepWarning, true);
- }
-
}
private OnSweepListener mSweepListener = new OnSweepListener() {
public void onSweep(ChartSweepView sweep, boolean sweepDone) {
- mSeries.setPrimaryRange(mSweepLeft.getValue(), mSweepRight.getValue());
+ updatePrimaryRange();
// update detail list only when done sweeping
if (sweepDone && mListener != null) {
@@ -236,13 +222,26 @@
mSweepLeft.setValue(sweepMin);
mSweepRight.setValue(sweepMax);
- mSeries.setPrimaryRange(sweepMin, sweepMax);
+ updatePrimaryRange();
requestLayout();
mSeries.generatePath();
mSeries.invalidate();
}
+ private void updatePrimaryRange() {
+ final long left = mSweepLeft.getValue();
+ final long right = mSweepRight.getValue();
+
+ // prefer showing primary range on detail series, when available
+ if (mDetailSeries.getVisibility() == View.VISIBLE) {
+ mDetailSeries.setPrimaryRange(left, right);
+ mSeries.setPrimaryRange(0, 0);
+ } else {
+ mSeries.setPrimaryRange(left, right);
+ }
+ }
+
public static class TimeAxis implements ChartAxis {
private static final long TICK_INTERVAL = DateUtils.DAY_IN_MILLIS * 7;