Data Usage, materialized!
Asset drop so Data Usage matches new Material spec. Removes time dimension sweeps, so we now summarize the entire visible axis. Fix time axis labels to not draw outside clip bounds. Remove pie chart. No more checkboxes in menus. Telephony items like roaming are moved back to cellular settings. Start wiring up multi-SIM support. Bug: 15760500, 16019700, 16289924, 16303795 Change-Id: Ie8f4821962319bb82ff4bc2f13f1f66ba1bdfe65
@@ -1659,7 +1659,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="Settings$NotificationAccessSettingsActivity"
|
<activity android:name="Settings$NotificationAccessSettingsActivity"
|
||||||
android:label="@string/manage_notification_access"
|
android:label="@string/manage_notification_access_title"
|
||||||
android:taskAffinity="">
|
android:taskAffinity="">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 152 B |
Before Width: | Height: | Size: 122 B |
Before Width: | Height: | Size: 125 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 535 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 526 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 151 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 126 B |
Before Width: | Height: | Size: 125 B |
Before Width: | Height: | Size: 878 B |
Before Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 391 B |
Before Width: | Height: | Size: 812 B |
Before Width: | Height: | Size: 982 B |
Before Width: | Height: | Size: 860 B |
Before Width: | Height: | Size: 906 B After Width: | Height: | Size: 384 B |
Before Width: | Height: | Size: 814 B |
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 154 B |
Before Width: | Height: | Size: 138 B |
Before Width: | Height: | Size: 133 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 691 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 694 B |
Before Width: | Height: | Size: 1.6 KiB |
BIN
res/drawable-xxhdpi/data_grid_border.9.png
Normal file
After Width: | Height: | Size: 162 B |
BIN
res/drawable-xxhdpi/data_sweep_limit_activated.9.png
Normal file
After Width: | Height: | Size: 983 B |
BIN
res/drawable-xxhdpi/data_sweep_warning_activated.9.png
Normal file
After Width: | Height: | Size: 1008 B |
BIN
res/drawable-xxxhdpi/data_grid_border.9.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-xxxhdpi/data_sweep_limit_activated.9.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
res/drawable-xxxhdpi/data_sweep_warning_activated.9.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
@@ -14,10 +14,6 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
<item android:drawable="@drawable/data_sweep_limit_activated" />
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
|
||||||
|
|
||||||
<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>
|
</selector>
|
||||||
|
@@ -14,10 +14,6 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
<item android:drawable="@drawable/data_sweep_warning_activated" />
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
|
||||||
|
|
||||||
<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>
|
</selector>
|
||||||
|
@@ -18,14 +18,14 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:paddingTop="8dip"
|
android:paddingTop="14dp"
|
||||||
android:paddingBottom="8dip"
|
android:paddingBottom="14dp"
|
||||||
android:columnCount="3">
|
android:columnCount="3">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@android:id/icon"
|
android:id="@android:id/icon"
|
||||||
android:layout_width="@android:dimen/app_icon_size"
|
android:layout_width="40dp"
|
||||||
android:layout_height="@android:dimen/app_icon_size"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:scaleType="fitXY"
|
android:scaleType="fitXY"
|
||||||
android:layout_rowSpan="3"
|
android:layout_rowSpan="3"
|
||||||
@@ -39,21 +39,23 @@
|
|||||||
android:layout_marginTop="2dip"
|
android:layout_marginTop="2dip"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textAlignment="viewStart" />
|
android:textAlignment="viewStart" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/text1"
|
android:id="@android:id/text1"
|
||||||
android:layout_marginStart="6dip"
|
android:layout_marginStart="6dip"
|
||||||
android:layout_marginTop="2dip"
|
android:layout_marginTop="2dip"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@android:id/progress"
|
android:id="@android:id/progress"
|
||||||
android:layout_height="8dip"
|
android:layout_height="wrap_content"
|
||||||
android:layout_columnSpan="2"
|
android:layout_columnSpan="2"
|
||||||
android:layout_gravity="fill_horizontal|top"
|
android:layout_gravity="fill_horizontal|top"
|
||||||
android:layout_marginTop="8dip"
|
android:layout_marginTop="4dip"
|
||||||
android:max="100"
|
android:max="100"
|
||||||
android:progressDrawable="@drawable/data_usage_bar"
|
android:progressDrawable="@drawable/data_usage_bar"
|
||||||
style="?android:attr/progressBarStyleHorizontal" />
|
style="?android:attr/progressBarStyleHorizontal" />
|
||||||
|
@@ -14,10 +14,24 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:textAlignment="viewStart" />
|
android:textAlignment="viewStart" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textAlignment="viewEnd" />
|
||||||
|
</LinearLayout>
|
||||||
|
@@ -14,65 +14,48 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<!-- NOTE: this explicitly uses right/left padding, since the
|
||||||
|
graph isn't swapped in RTL languages -->
|
||||||
<com.android.settings.widget.ChartDataUsageView
|
<com.android.settings.widget.ChartDataUsageView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
|
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
|
||||||
android:id="@+id/chart"
|
android:id="@+id/chart"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/data_usage_chart_height"
|
android:layout_height="@dimen/data_usage_chart_height"
|
||||||
android:layout_marginStart="-16dip"
|
android:paddingLeft="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginEnd="-16dip"
|
android:paddingRight="40dp"
|
||||||
android:layout_marginBottom="-32dip"
|
android:paddingTop="16dp"
|
||||||
android:paddingStart="24dip"
|
android:paddingBottom="24dp">
|
||||||
android:paddingEnd="24dip"
|
|
||||||
android:paddingTop="16dip"
|
|
||||||
android:paddingBottom="48dip"
|
|
||||||
settings:optimalWidth="@dimen/data_usage_chart_optimalWidth"
|
|
||||||
settings:optimalWidthWeight="0.4">
|
|
||||||
|
|
||||||
<com.android.settings.widget.ChartGridView
|
<com.android.settings.widget.ChartGridView
|
||||||
android:id="@+id/grid"
|
android:id="@+id/grid"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
settings:primaryDrawable="@drawable/data_grid_primary"
|
android:paddingBottom="24dp"
|
||||||
settings:secondaryDrawable="@drawable/data_grid_secondary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
settings:borderDrawable="@drawable/data_grid_border"
|
android:textAppearance="@android:style/TextAppearance.Material.Caption"
|
||||||
settings:labelColor="@android:color/holo_blue_light" />
|
settings:borderDrawable="@drawable/data_grid_border" />
|
||||||
|
|
||||||
<com.android.settings.widget.ChartNetworkSeriesView
|
<com.android.settings.widget.ChartNetworkSeriesView
|
||||||
android:id="@+id/series"
|
android:id="@+id/series"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
settings:strokeColor="@android:color/holo_blue_light"
|
settings:strokeColor="#00000000"
|
||||||
settings:fillColor="#c033b5e5"
|
settings:fillColor="#ff009688"
|
||||||
settings:fillColorSecondary="#6633b5e5" />
|
settings:fillColorSecondary="#ff80cbc4"
|
||||||
|
settings:safeRegion="3dp" />
|
||||||
|
|
||||||
<com.android.settings.widget.ChartNetworkSeriesView
|
<com.android.settings.widget.ChartNetworkSeriesView
|
||||||
android:id="@+id/detail_series"
|
android:id="@+id/detail_series"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="start|bottom"
|
android:layout_gravity="start|bottom"
|
||||||
settings:strokeColor="@color/theme_accent"
|
settings:strokeColor="#00000000"
|
||||||
settings:fillColor="#c0ba7f3e"
|
settings:fillColor="#ff009688"
|
||||||
settings:fillColorSecondary="#60ba7f3e" />
|
settings:fillColorSecondary="#ff009688"
|
||||||
|
settings:safeRegion="3dp" />
|
||||||
<com.android.settings.widget.ChartSweepView
|
|
||||||
android:id="@+id/sweep_left"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
settings:sweepDrawable="@drawable/data_sweep_left"
|
|
||||||
settings:followAxis="horizontal"
|
|
||||||
settings:neighborMargin="5dip" />
|
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
|
||||||
android:id="@+id/sweep_right"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
settings:sweepDrawable="@drawable/data_sweep_right"
|
|
||||||
settings:followAxis="horizontal"
|
|
||||||
settings:neighborMargin="5dip" />
|
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
<com.android.settings.widget.ChartSweepView
|
||||||
android:id="@+id/sweep_warning"
|
android:id="@+id/sweep_warning"
|
||||||
@@ -84,7 +67,8 @@
|
|||||||
settings:neighborMargin="5dip"
|
settings:neighborMargin="5dip"
|
||||||
settings:labelSize="60dip"
|
settings:labelSize="60dip"
|
||||||
settings:labelTemplate="@string/data_usage_sweep_warning"
|
settings:labelTemplate="@string/data_usage_sweep_warning"
|
||||||
settings:labelColor="#f7931d" />
|
settings:labelColor="#ff37474f"
|
||||||
|
settings:safeRegion="4dp" />
|
||||||
|
|
||||||
<com.android.settings.widget.ChartSweepView
|
<com.android.settings.widget.ChartSweepView
|
||||||
android:id="@+id/sweep_limit"
|
android:id="@+id/sweep_limit"
|
||||||
@@ -96,6 +80,7 @@
|
|||||||
settings:neighborMargin="5dip"
|
settings:neighborMargin="5dip"
|
||||||
settings:labelSize="60dip"
|
settings:labelSize="60dip"
|
||||||
settings:labelTemplate="@string/data_usage_sweep_limit"
|
settings:labelTemplate="@string/data_usage_sweep_limit"
|
||||||
settings:labelColor="#c01a2c" />
|
settings:labelColor="#fff4511e"
|
||||||
|
settings:safeRegion="4dp" />
|
||||||
|
|
||||||
</com.android.settings.widget.ChartDataUsageView>
|
</com.android.settings.widget.ChartDataUsageView>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,10 +14,14 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
android:id="@android:id/text1"
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
style="?android:attr/spinnerItemStyle"
|
||||||
|
android:singleLine="true"
|
||||||
<item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_right_activated" />
|
android:layout_width="match_parent"
|
||||||
<item android:drawable="@drawable/data_sweep_right_default" />
|
android:layout_height="wrap_content"
|
||||||
</selector>
|
android:paddingStart="0dp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textAlignment="inherit" />
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,10 +14,13 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:enterFadeDuration="@android:integer/config_mediumAnimTime"
|
android:id="@android:id/text1"
|
||||||
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
|
style="?android:attr/spinnerDropDownItemStyle"
|
||||||
|
android:singleLine="true"
|
||||||
<item android:state_activated="true" android:state_enabled="true" android:drawable="@drawable/data_sweep_left_activated" />
|
android:layout_width="match_parent"
|
||||||
<item android:drawable="@drawable/data_sweep_left_default" />
|
android:layout_height="?android:attr/listPreferredItemHeightSmall"
|
||||||
</selector>
|
android:ellipsize="marquee"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textAlignment="inherit" />
|
@@ -15,22 +15,30 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/cycles"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="40dip"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||||
android:text="@string/data_usage_cycle" />
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/cycles_spinner"
|
android:id="@+id/cycles_spinner"
|
||||||
android:layout_width="0dip"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1" />
|
android:layout_gravity="center_vertical"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cycle_summary"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textAlignment="viewEnd" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
android:id="@+id/app_detail"
|
android:id="@+id/app_detail"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="4dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
@@ -26,82 +27,107 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:layout_marginBottom="16dip"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/app_icon"
|
||||||
|
android:layout_width="@android:dimen/app_icon_size"
|
||||||
|
android:layout_height="@android:dimen/app_icon_size"
|
||||||
|
android:layout_marginEnd="8dip"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:contentDescription="@null" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dip"
|
android:layout_width="0dip"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_marginTop="8dip"
|
android:layout_marginTop="8dip"
|
||||||
android:layout_marginEnd="8dip"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/app_icon"
|
|
||||||
android:layout_width="48dip"
|
|
||||||
android:layout_height="48dip"
|
|
||||||
android:scaleType="centerInside"
|
|
||||||
android:contentDescription="@null" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/app_titles"
|
android:id="@+id/app_titles"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="4dip"
|
||||||
android:textAlignment="viewStart" />
|
android:textAlignment="viewStart" />
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dip"
|
android:layout_weight="1"
|
||||||
android:textColor="@color/theme_accent"
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
android:text="@string/data_usage_label_foreground"
|
android:text="@string/data_usage_label_foreground"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:textAlignment="viewStart" />
|
android:textAlignment="viewStart" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/app_foreground"
|
android:id="@+id/app_foreground"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@color/theme_accent"
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
android:textAlignment="viewStart" />
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textAlignment="viewEnd" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/app_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dip"
|
android:layout_weight="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="marquee"
|
||||||
android:text="@string/data_usage_label_background"
|
android:text="@string/data_usage_label_background"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:textAlignment="viewStart" />
|
android:textAlignment="viewStart" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/app_background"
|
android:id="@+id/app_background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="viewStart" />
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textAlignment="viewEnd" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.android.settings.widget.PieChartView
|
|
||||||
android:id="@+id/app_pie_chart"
|
|
||||||
android:layout_width="160dip"
|
|
||||||
android:layout_height="160dip" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<Button
|
<LinearLayout
|
||||||
android:id="@+id/app_settings"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:layout_marginTop="16dip"
|
|
||||||
android:layout_marginBottom="16dip"
|
android:layout_marginBottom="16dip"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="0.5" />
|
||||||
|
<Button
|
||||||
|
android:id="@+id/app_settings"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
android:text="@string/data_usage_app_settings" />
|
android:text="@string/data_usage_app_settings" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/app_switches"
|
android:id="@+id/app_switches"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical" />
|
android:orientation="vertical"
|
||||||
|
android:showDividers="beginning|middle"
|
||||||
|
android:divider="?android:attr/listDivider" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -19,9 +19,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false">
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/network_switches_container"
|
android:id="@+id/network_switches_container"
|
||||||
@@ -36,29 +34,39 @@
|
|||||||
android:divider="?android:attr/listDivider" />
|
android:divider="?android:attr/listDivider" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/data_usage_cycles" />
|
|
||||||
<include layout="@layout/data_usage_chart" />
|
<include layout="@layout/data_usage_chart" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/usage_summary"
|
android:id="@+id/disclaimer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/data_usage_disclaimer"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:paddingTop="8dip"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="8dip"
|
android:paddingBottom="0dp" />
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@android:id/empty"
|
android:id="@android:id/empty"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:text="@string/data_usage_empty"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:paddingBottom="8dip"
|
android:paddingTop="4dp"
|
||||||
android:text="@string/data_usage_empty"
|
android:paddingBottom="0dp" />
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/stupid_padding"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="8dp" />
|
||||||
|
|
||||||
<include layout="@layout/data_usage_detail" />
|
<include layout="@layout/data_usage_detail" />
|
||||||
|
|
||||||
|
@@ -17,23 +17,26 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="48dip"
|
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
android:background="?android:attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:paddingTop="6dip"
|
android:paddingTop="16dip"
|
||||||
android:paddingBottom="6dip">
|
android:paddingBottom="16dip">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+android:id/title"
|
android:id="@+android:id/title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:fadingEdge="horizontal" />
|
android:fadingEdge="horizontal" />
|
||||||
|
|
||||||
@@ -44,9 +47,10 @@
|
|||||||
android:layout_below="@android:id/title"
|
android:layout_below="@android:id/title"
|
||||||
android:layout_alignStart="@android:id/title"
|
android:layout_alignStart="@android:id/title"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAlignment="viewStart"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:maxLines="4" />
|
android:maxLines="10" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
@@ -54,7 +58,8 @@
|
|||||||
android:id="@android:id/widget_frame"
|
android:id="@android:id/widget_frame"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center_vertical"
|
android:minWidth="58dip"
|
||||||
|
android:gravity="end|center_vertical"
|
||||||
android:orientation="vertical" />
|
android:orientation="vertical" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -15,33 +15,24 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item
|
|
||||||
android:id="@+id/data_usage_menu_roaming"
|
|
||||||
android:title="@string/data_usage_menu_roaming"
|
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/data_usage_menu_restrict_background"
|
android:id="@+id/data_usage_menu_restrict_background"
|
||||||
android:title="@string/data_usage_menu_restrict_background"
|
android:title="@string/data_usage_menu_restrict_background" />
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/data_usage_menu_split_4g"
|
|
||||||
android:title="@string/data_usage_menu_split_4g"
|
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/data_usage_menu_auto_sync"
|
|
||||||
android:title="@string/data_usage_menu_auto_sync"
|
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/data_usage_menu_show_wifi"
|
android:id="@+id/data_usage_menu_show_wifi"
|
||||||
android:title="@string/data_usage_menu_show_wifi"
|
android:title="@string/data_usage_menu_show_wifi" />
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/data_usage_menu_show_ethernet"
|
android:id="@+id/data_usage_menu_show_ethernet"
|
||||||
android:title="@string/data_usage_menu_show_ethernet"
|
android:title="@string/data_usage_menu_show_ethernet" />
|
||||||
android:checkable="true" />
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/data_usage_menu_metered"
|
android:id="@+id/data_usage_menu_metered"
|
||||||
android:title="@string/data_usage_menu_metered" />
|
android:title="@string/data_usage_menu_metered" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/data_usage_menu_sim_cards"
|
||||||
|
android:title="@string/data_usage_menu_sim_cards" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/data_usage_menu_cellular_networks"
|
||||||
|
android:title="@string/data_usage_menu_cellular_networks" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/data_usage_menu_help"
|
android:id="@+id/data_usage_menu_help"
|
||||||
android:title="@string/help_label" />
|
android:title="@string/help_label" />
|
||||||
|
@@ -75,19 +75,22 @@
|
|||||||
<attr name="labelSize" format="dimension" />
|
<attr name="labelSize" format="dimension" />
|
||||||
<attr name="labelTemplate" format="reference" />
|
<attr name="labelTemplate" format="reference" />
|
||||||
<attr name="labelColor" format="color" />
|
<attr name="labelColor" format="color" />
|
||||||
|
<attr name="safeRegion" format="dimension" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="ChartGridView">
|
<declare-styleable name="ChartGridView">
|
||||||
<attr name="primaryDrawable" format="reference" />
|
<attr name="primaryDrawable" format="reference" />
|
||||||
<attr name="secondaryDrawable" format="reference" />
|
<attr name="secondaryDrawable" format="reference" />
|
||||||
<attr name="borderDrawable" format="reference" />
|
<attr name="borderDrawable" format="reference" />
|
||||||
<attr name="labelColor" />
|
<attr name="android:textColor" />
|
||||||
|
<attr name="android:textAppearance" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="ChartNetworkSeriesView">
|
<declare-styleable name="ChartNetworkSeriesView">
|
||||||
<attr name="strokeColor" format="color" />
|
<attr name="strokeColor" format="color" />
|
||||||
<attr name="fillColor" format="color" />
|
<attr name="fillColor" format="color" />
|
||||||
<attr name="fillColorSecondary" format="color" />
|
<attr name="fillColorSecondary" format="color" />
|
||||||
|
<attr name="safeRegion" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<attr name="apnPreferenceStyle" format="reference" />
|
<attr name="apnPreferenceStyle" format="reference" />
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<dimen name="battery_history_chart_height">120dp</dimen>
|
<dimen name="battery_history_chart_height">120dp</dimen>
|
||||||
|
|
||||||
<dimen name="data_usage_chart_height">252dip</dimen>
|
<dimen name="data_usage_chart_height">228dip</dimen>
|
||||||
<dimen name="data_usage_chart_optimalWidth">440dip</dimen>
|
<dimen name="data_usage_chart_optimalWidth">440dip</dimen>
|
||||||
|
|
||||||
<dimen name="volume_seekbar_side_margin">8dip</dimen>
|
<dimen name="volume_seekbar_side_margin">8dip</dimen>
|
||||||
|
@@ -4784,20 +4784,31 @@
|
|||||||
<string name="data_usage_data_limit">Set data limit</string>
|
<string name="data_usage_data_limit">Set data limit</string>
|
||||||
<!-- Title for option to pick visible time range from a list available usage periods. [CHAR LIMIT=25] -->
|
<!-- Title for option to pick visible time range from a list available usage periods. [CHAR LIMIT=25] -->
|
||||||
<string name="data_usage_cycle">Data usage cycle</string>
|
<string name="data_usage_cycle">Data usage cycle</string>
|
||||||
<!-- Title for checkbox menu option to enable mobile data when roaming. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to enable mobile data when roaming. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_roaming">Data roaming</string>
|
<string name="data_usage_menu_roaming">Data roaming</string>
|
||||||
<!-- Title for checkbox menu option to restrict background data usage. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to restrict background data usage. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_restrict_background">Restrict background data</string>
|
<string name="data_usage_menu_restrict_background">Restrict background data</string>
|
||||||
<!-- Title for checkbox menu option to show 4G mobile data usage separate from other mobile data usage. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to allow background data usage. [CHAR LIMIT=26] -->
|
||||||
|
<string name="data_usage_menu_allow_background">Allow background data</string>
|
||||||
|
<!-- Title for menu option to show 4G mobile data usage separate from other mobile data usage. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_split_4g">Separate 4G usage</string>
|
<string name="data_usage_menu_split_4g">Separate 4G usage</string>
|
||||||
<!-- Title for checkbox menu option to show Wi-Fi data usage. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to show Wi-Fi data usage. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_show_wifi">Show Wi\u2011Fi</string>
|
<string name="data_usage_menu_show_wifi">Show Wi\u2011Fi</string>
|
||||||
<!-- Title for checkbox menu option to show Ethernet data usage. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to hide Wi-Fi data usage. [CHAR LIMIT=26] -->
|
||||||
|
<string name="data_usage_menu_hide_wifi">Hide Wi\u2011Fi</string>
|
||||||
|
<!-- Title for menu option to show Ethernet data usage. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_show_ethernet">Show Ethernet usage</string>
|
<string name="data_usage_menu_show_ethernet">Show Ethernet usage</string>
|
||||||
|
<!-- Title for menu option to hide Ethernet data usage. [CHAR LIMIT=26] -->
|
||||||
|
<string name="data_usage_menu_hide_ethernet">Hide Ethernet usage</string>
|
||||||
<!-- Title for menu option to configure metered networks. [CHAR LIMIT=26] -->
|
<!-- Title for menu option to configure metered networks. [CHAR LIMIT=26] -->
|
||||||
<string name="data_usage_menu_metered">Mobile hotspots</string>
|
<string name="data_usage_menu_metered">Network restrictions</string>
|
||||||
<!-- Title for menu option to enable global auto-sync of account data -->
|
<!-- Title for menu option to enable global auto-sync of account data -->
|
||||||
<string name="data_usage_menu_auto_sync">Auto-sync data</string>
|
<string name="data_usage_menu_auto_sync">Auto-sync data</string>
|
||||||
|
<!-- Title for menu option to show details for all SIM cards. [CHAR LIMIT=26] -->
|
||||||
|
<string name="data_usage_menu_sim_cards">SIM cards</string>
|
||||||
|
<!-- Title for menu option to show details for all cellular networks. [CHAR LIMIT=26] -->
|
||||||
|
<string name="data_usage_menu_cellular_networks">Cellular networks</string>
|
||||||
|
|
||||||
<!-- Title for menu option to enable global auto-sync of personal account data [CHAR LIMIT=30] -->
|
<!-- Title for menu option to enable global auto-sync of personal account data [CHAR LIMIT=30] -->
|
||||||
<string name="account_settings_menu_auto_sync">Auto-sync data</string>
|
<string name="account_settings_menu_auto_sync">Auto-sync data</string>
|
||||||
<!-- Title for menu option to enable global auto-sync of personal account data [CHAR LIMIT=30] -->
|
<!-- Title for menu option to enable global auto-sync of personal account data [CHAR LIMIT=30] -->
|
||||||
@@ -4858,7 +4869,7 @@
|
|||||||
<!-- Data Usage Background label. [CHAR LIMIT=40] -->
|
<!-- Data Usage Background label. [CHAR LIMIT=40] -->
|
||||||
<string name="data_usage_background_label">Background:</string>
|
<string name="data_usage_background_label">Background:</string>
|
||||||
<!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
|
<!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_app_settings">View app settings</string>
|
<string name="data_usage_app_settings">App settings</string>
|
||||||
<!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=40] -->
|
<!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=40] -->
|
||||||
<string name="data_usage_app_restrict_background">Restrict app background data</string>
|
<string name="data_usage_app_restrict_background">Restrict app background data</string>
|
||||||
<!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=64] -->
|
<!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=64] -->
|
||||||
@@ -4930,15 +4941,18 @@
|
|||||||
<string name="data_usage_total_during_range_mobile" product="default"><xliff:g id="range" example="Jul 1 - Jul 31">%2$s</xliff:g>: about <xliff:g id="total" example="128KB">%1$s</xliff:g> used, as measured by your phone. Your carrier\'s data usage accounting may differ.</string>
|
<string name="data_usage_total_during_range_mobile" product="default"><xliff:g id="range" example="Jul 1 - Jul 31">%2$s</xliff:g>: about <xliff:g id="total" example="128KB">%1$s</xliff:g> used, as measured by your phone. Your carrier\'s data usage accounting may differ.</string>
|
||||||
|
|
||||||
<!-- Dialog title for selecting metered networks. [CHAR LIMIT=25] -->
|
<!-- Dialog title for selecting metered networks. [CHAR LIMIT=25] -->
|
||||||
<string name="data_usage_metered_title">Mobile hotspots</string>
|
<string name="data_usage_metered_title">Network restrictions</string>
|
||||||
<!-- Dialog body for selecting paid networks. [CHAR LIMIT=NONE] -->
|
<!-- Dialog body for selecting paid networks. [CHAR LIMIT=NONE] -->
|
||||||
<string name="data_usage_metered_body">Select the Wi\u2011Fi networks which are mobile hotspots. Apps can be restricted from using these networks when in the background. Apps may also warn before using these networks for large downloads.</string>
|
<string name="data_usage_metered_body">Metered networks are treated like cellular when background data is restricted. Apps may warn before using these networks for large downloads.</string>
|
||||||
<!-- Header for list of mobile networks. [CHAR LIMIT=32] -->
|
<!-- Header for list of mobile networks. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_metered_mobile">Cellular networks</string>
|
<string name="data_usage_metered_mobile">Cellular networks</string>
|
||||||
<!-- Header for list of Wi-Fi networks. [CHAR LIMIT=32] -->
|
<!-- Header for list of Wi-Fi networks. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_metered_wifi">Wi\u2011Fi networks</string>
|
<string name="data_usage_metered_wifi">Metered Wi\u2011Fi networks</string>
|
||||||
<!-- Body text prompting user to enable Wi-Fi to configure metered networks. [CHAR LIMIT=64] -->
|
<!-- Body text prompting user to enable Wi-Fi to configure metered networks. [CHAR LIMIT=64] -->
|
||||||
<string name="data_usage_metered_wifi_disabled">To select mobile hotspots, turn Wi\u2011Fi on.</string>
|
<string name="data_usage_metered_wifi_disabled">To select metered networks, turn Wi\u2011Fi on.</string>
|
||||||
|
|
||||||
|
<!-- Disclaimer string for data usage measured by device. [CHAR LIMIT=80] -->
|
||||||
|
<string name="data_usage_disclaimer">Carrier data accounting may differ from your device.</string>
|
||||||
|
|
||||||
<!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
|
<!-- Button at the bottom of the CryptKeeper screen to make an emergency call. -->
|
||||||
<string name="cryptkeeper_emergency_call">Emergency call</string>
|
<string name="cryptkeeper_emergency_call">Emergency call</string>
|
||||||
|
@@ -17,11 +17,6 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:title="@string/display_settings">
|
android:title="@string/display_settings">
|
||||||
|
|
||||||
<Preference
|
|
||||||
android:summary="@string/data_usage_metered_body"
|
|
||||||
android:persistent="false"
|
|
||||||
android:selectable="false" />
|
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="mobile"
|
android:key="mobile"
|
||||||
android:title="@string/data_usage_metered_mobile"
|
android:title="@string/data_usage_metered_mobile"
|
||||||
@@ -40,4 +35,9 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:summary="@string/data_usage_metered_body"
|
||||||
|
android:persistent="false"
|
||||||
|
android:selectable="false" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@@ -55,6 +55,7 @@ import android.app.DialogFragment;
|
|||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.app.LoaderManager.LoaderCallbacks;
|
import android.app.LoaderManager.LoaderCallbacks;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -63,6 +64,7 @@ import android.content.Loader;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@@ -107,9 +109,6 @@ import android.widget.AdapterView.OnItemSelectedListener;
|
|||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.BaseAdapter;
|
import android.widget.BaseAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
@@ -138,7 +137,6 @@ import com.android.settings.search.Indexable;
|
|||||||
import com.android.settings.search.SearchIndexableRaw;
|
import com.android.settings.search.SearchIndexableRaw;
|
||||||
import com.android.settings.widget.ChartDataUsageView;
|
import com.android.settings.widget.ChartDataUsageView;
|
||||||
import com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
|
import com.android.settings.widget.ChartDataUsageView.DataUsageChartListener;
|
||||||
import com.android.settings.widget.PieChartView;
|
|
||||||
import com.google.android.collect.Lists;
|
import com.google.android.collect.Lists;
|
||||||
|
|
||||||
import libcore.util.Objects;
|
import libcore.util.Objects;
|
||||||
@@ -170,7 +168,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
private static final String TAB_ETHERNET = "ethernet";
|
private static final String TAB_ETHERNET = "ethernet";
|
||||||
|
|
||||||
private static final String TAG_CONFIRM_DATA_DISABLE = "confirmDataDisable";
|
private static final String TAG_CONFIRM_DATA_DISABLE = "confirmDataDisable";
|
||||||
private static final String TAG_CONFIRM_DATA_ROAMING = "confirmDataRoaming";
|
|
||||||
private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
|
private static final String TAG_CONFIRM_LIMIT = "confirmLimit";
|
||||||
private static final String TAG_CYCLE_EDITOR = "cycleEditor";
|
private static final String TAG_CYCLE_EDITOR = "cycleEditor";
|
||||||
private static final String TAG_WARNING_EDITOR = "warningEditor";
|
private static final String TAG_WARNING_EDITOR = "warningEditor";
|
||||||
@@ -189,15 +186,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
private static final int LOADER_CHART_DATA = 2;
|
private static final int LOADER_CHART_DATA = 2;
|
||||||
private static final int LOADER_SUMMARY = 3;
|
private static final int LOADER_SUMMARY = 3;
|
||||||
|
|
||||||
private static final int FOREGROUND_BYTES_COLOR = 0xff009688;
|
|
||||||
private static final int DEFAULT_BYTES_COLOR = 0xffced7db;
|
|
||||||
|
|
||||||
private INetworkManagementService mNetworkService;
|
private INetworkManagementService mNetworkService;
|
||||||
private INetworkStatsService mStatsService;
|
private INetworkStatsService mStatsService;
|
||||||
private NetworkPolicyManager mPolicyManager;
|
private NetworkPolicyManager mPolicyManager;
|
||||||
private TelephonyManager mTelephonyManager;
|
private TelephonyManager mTelephonyManager;
|
||||||
|
|
||||||
|
|
||||||
private INetworkStatsSession mStatsSession;
|
private INetworkStatsSession mStatsSession;
|
||||||
|
|
||||||
private static final String PREF_FILE = "data_usage";
|
private static final String PREF_FILE = "data_usage";
|
||||||
@@ -219,29 +212,33 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
private ViewGroup mNetworkSwitchesContainer;
|
private ViewGroup mNetworkSwitchesContainer;
|
||||||
private LinearLayout mNetworkSwitches;
|
private LinearLayout mNetworkSwitches;
|
||||||
|
private boolean mDataEnabledSupported;
|
||||||
private Switch mDataEnabled;
|
private Switch mDataEnabled;
|
||||||
private View mDataEnabledView;
|
private View mDataEnabledView;
|
||||||
private CheckBox mDisableAtLimit;
|
private boolean mDisableAtLimitSupported;
|
||||||
|
private Switch mDisableAtLimit;
|
||||||
private View mDisableAtLimitView;
|
private View mDisableAtLimitView;
|
||||||
|
|
||||||
private View mCycleView;
|
private View mCycleView;
|
||||||
private Spinner mCycleSpinner;
|
private Spinner mCycleSpinner;
|
||||||
private CycleAdapter mCycleAdapter;
|
private CycleAdapter mCycleAdapter;
|
||||||
|
private TextView mCycleSummary;
|
||||||
|
|
||||||
private ChartDataUsageView mChart;
|
private ChartDataUsageView mChart;
|
||||||
private TextView mUsageSummary;
|
private View mDisclaimer;
|
||||||
private TextView mEmpty;
|
private TextView mEmpty;
|
||||||
|
private View mStupidPadding;
|
||||||
|
|
||||||
private View mAppDetail;
|
private View mAppDetail;
|
||||||
private ImageView mAppIcon;
|
private ImageView mAppIcon;
|
||||||
private ViewGroup mAppTitles;
|
private ViewGroup mAppTitles;
|
||||||
private PieChartView mAppPieChart;
|
private TextView mAppTotal;
|
||||||
private TextView mAppForeground;
|
private TextView mAppForeground;
|
||||||
private TextView mAppBackground;
|
private TextView mAppBackground;
|
||||||
private Button mAppSettings;
|
private Button mAppSettings;
|
||||||
|
|
||||||
private LinearLayout mAppSwitches;
|
private LinearLayout mAppSwitches;
|
||||||
private CheckBox mAppRestrict;
|
private Switch mAppRestrict;
|
||||||
private View mAppRestrictView;
|
private View mAppRestrictView;
|
||||||
|
|
||||||
private boolean mShowWifi = false;
|
private boolean mShowWifi = false;
|
||||||
@@ -259,9 +256,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
private String mCurrentTab = null;
|
private String mCurrentTab = null;
|
||||||
private String mIntentTab = null;
|
private String mIntentTab = null;
|
||||||
|
|
||||||
private MenuItem mMenuDataRoaming;
|
|
||||||
private MenuItem mMenuRestrictBackground;
|
private MenuItem mMenuRestrictBackground;
|
||||||
private MenuItem mMenuAutoSync;
|
private MenuItem mMenuShowWifi;
|
||||||
|
private MenuItem mMenuShowEthernet;
|
||||||
|
private MenuItem mMenuSimCards;
|
||||||
|
private MenuItem mMenuCellularNetworks;
|
||||||
|
|
||||||
/** Flag used to ignore listeners during binding. */
|
/** Flag used to ignore listeners during binding. */
|
||||||
private boolean mBinding;
|
private boolean mBinding;
|
||||||
@@ -359,13 +358,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mNetworkSwitches = (LinearLayout) mHeader.findViewById(R.id.network_switches);
|
mNetworkSwitches = (LinearLayout) mHeader.findViewById(R.id.network_switches);
|
||||||
|
|
||||||
mDataEnabled = new Switch(inflater.getContext());
|
mDataEnabled = new Switch(inflater.getContext());
|
||||||
|
mDataEnabled.setClickable(false);
|
||||||
|
mDataEnabled.setFocusable(false);
|
||||||
mDataEnabledView = inflatePreference(inflater, mNetworkSwitches, mDataEnabled);
|
mDataEnabledView = inflatePreference(inflater, mNetworkSwitches, mDataEnabled);
|
||||||
mDataEnabledView.setTag(R.id.preference_highlight_key,
|
mDataEnabledView.setTag(R.id.preference_highlight_key,
|
||||||
DATA_USAGE_ENABLE_MOBILE_KEY);
|
DATA_USAGE_ENABLE_MOBILE_KEY);
|
||||||
mDataEnabled.setOnCheckedChangeListener(mDataEnabledListener);
|
mDataEnabledView.setClickable(true);
|
||||||
|
mDataEnabledView.setFocusable(true);
|
||||||
|
mDataEnabledView.setOnClickListener(mDataEnabledListener);
|
||||||
mNetworkSwitches.addView(mDataEnabledView);
|
mNetworkSwitches.addView(mDataEnabledView);
|
||||||
|
|
||||||
mDisableAtLimit = new CheckBox(inflater.getContext());
|
mDisableAtLimit = new Switch(inflater.getContext());
|
||||||
mDisableAtLimit.setClickable(false);
|
mDisableAtLimit.setClickable(false);
|
||||||
mDisableAtLimit.setFocusable(false);
|
mDisableAtLimit.setFocusable(false);
|
||||||
mDisableAtLimitView = inflatePreference(inflater, mNetworkSwitches, mDisableAtLimit);
|
mDisableAtLimitView = inflatePreference(inflater, mNetworkSwitches, mDisableAtLimit);
|
||||||
@@ -375,15 +378,16 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mDisableAtLimitView.setFocusable(true);
|
mDisableAtLimitView.setFocusable(true);
|
||||||
mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
|
mDisableAtLimitView.setOnClickListener(mDisableAtLimitListener);
|
||||||
mNetworkSwitches.addView(mDisableAtLimitView);
|
mNetworkSwitches.addView(mDisableAtLimitView);
|
||||||
}
|
|
||||||
|
|
||||||
// bind cycle dropdown
|
mCycleView = inflater.inflate(R.layout.data_usage_cycles, mNetworkSwitches, false);
|
||||||
mCycleView = mHeader.findViewById(R.id.cycles);
|
|
||||||
mCycleView.setTag(R.id.preference_highlight_key, DATA_USAGE_CYCLE_KEY);
|
mCycleView.setTag(R.id.preference_highlight_key, DATA_USAGE_CYCLE_KEY);
|
||||||
mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
|
mCycleSpinner = (Spinner) mCycleView.findViewById(R.id.cycles_spinner);
|
||||||
mCycleAdapter = new CycleAdapter(context);
|
mCycleAdapter = new CycleAdapter(context);
|
||||||
mCycleSpinner.setAdapter(mCycleAdapter);
|
mCycleSpinner.setAdapter(mCycleAdapter);
|
||||||
mCycleSpinner.setOnItemSelectedListener(mCycleListener);
|
mCycleSpinner.setOnItemSelectedListener(mCycleListener);
|
||||||
|
mCycleSummary = (TextView) mCycleView.findViewById(R.id.cycle_summary);
|
||||||
|
mNetworkSwitches.addView(mCycleView);
|
||||||
|
}
|
||||||
|
|
||||||
mChart = (ChartDataUsageView) mHeader.findViewById(R.id.chart);
|
mChart = (ChartDataUsageView) mHeader.findViewById(R.id.chart);
|
||||||
mChart.setListener(mChartListener);
|
mChart.setListener(mChartListener);
|
||||||
@@ -394,7 +398,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mAppDetail = mHeader.findViewById(R.id.app_detail);
|
mAppDetail = mHeader.findViewById(R.id.app_detail);
|
||||||
mAppIcon = (ImageView) mAppDetail.findViewById(R.id.app_icon);
|
mAppIcon = (ImageView) mAppDetail.findViewById(R.id.app_icon);
|
||||||
mAppTitles = (ViewGroup) mAppDetail.findViewById(R.id.app_titles);
|
mAppTitles = (ViewGroup) mAppDetail.findViewById(R.id.app_titles);
|
||||||
mAppPieChart = (PieChartView) mAppDetail.findViewById(R.id.app_pie_chart);
|
|
||||||
mAppForeground = (TextView) mAppDetail.findViewById(R.id.app_foreground);
|
mAppForeground = (TextView) mAppDetail.findViewById(R.id.app_foreground);
|
||||||
mAppBackground = (TextView) mAppDetail.findViewById(R.id.app_background);
|
mAppBackground = (TextView) mAppDetail.findViewById(R.id.app_background);
|
||||||
mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
|
mAppSwitches = (LinearLayout) mAppDetail.findViewById(R.id.app_switches);
|
||||||
@@ -402,7 +405,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
|
mAppSettings = (Button) mAppDetail.findViewById(R.id.app_settings);
|
||||||
mAppSettings.setOnClickListener(mAppSettingsListener);
|
mAppSettings.setOnClickListener(mAppSettingsListener);
|
||||||
|
|
||||||
mAppRestrict = new CheckBox(inflater.getContext());
|
mAppRestrict = new Switch(inflater.getContext());
|
||||||
mAppRestrict.setClickable(false);
|
mAppRestrict.setClickable(false);
|
||||||
mAppRestrict.setFocusable(false);
|
mAppRestrict.setFocusable(false);
|
||||||
mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict);
|
mAppRestrictView = inflatePreference(inflater, mAppSwitches, mAppRestrict);
|
||||||
@@ -412,8 +415,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mAppSwitches.addView(mAppRestrictView);
|
mAppSwitches.addView(mAppRestrictView);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUsageSummary = (TextView) mHeader.findViewById(R.id.usage_summary);
|
mDisclaimer = mHeader.findViewById(R.id.disclaimer);
|
||||||
mEmpty = (TextView) mHeader.findViewById(android.R.id.empty);
|
mEmpty = (TextView) mHeader.findViewById(android.R.id.empty);
|
||||||
|
mStupidPadding = mHeader.findViewById(R.id.stupid_padding);
|
||||||
|
|
||||||
mAdapter = new DataUsageAdapter(mUidDetailProvider, mInsetSide);
|
mAdapter = new DataUsageAdapter(mUidDetailProvider, mInsetSide);
|
||||||
mListView.setOnItemClickListener(mListListener);
|
mListView.setOnItemClickListener(mListListener);
|
||||||
@@ -480,39 +484,24 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
final boolean appDetailMode = isAppDetailMode();
|
final boolean appDetailMode = isAppDetailMode();
|
||||||
final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
|
final boolean isOwner = ActivityManager.getCurrentUser() == UserHandle.USER_OWNER;
|
||||||
|
|
||||||
mMenuDataRoaming = menu.findItem(R.id.data_usage_menu_roaming);
|
mMenuShowWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
|
||||||
mMenuDataRoaming.setVisible(hasReadyMobileRadio(context) && !appDetailMode);
|
// TODO: Define behavior of this sync button. See: http://b/16076571
|
||||||
mMenuDataRoaming.setChecked(getDataRoaming());
|
if (hasWifiRadio(context) && hasReadyMobileRadio(context)) {
|
||||||
|
mMenuShowWifi.setVisible(!appDetailMode);
|
||||||
|
} else {
|
||||||
|
mMenuShowWifi.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mMenuShowEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet);
|
||||||
|
if (hasEthernet(context) && hasReadyMobileRadio(context)) {
|
||||||
|
mMenuShowEthernet.setVisible(!appDetailMode);
|
||||||
|
} else {
|
||||||
|
mMenuShowEthernet.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
|
mMenuRestrictBackground = menu.findItem(R.id.data_usage_menu_restrict_background);
|
||||||
mMenuRestrictBackground.setVisible(
|
mMenuRestrictBackground.setVisible(
|
||||||
hasReadyMobileRadio(context) && isOwner && !appDetailMode);
|
hasReadyMobileRadio(context) && isOwner && !appDetailMode);
|
||||||
mMenuRestrictBackground.setChecked(mPolicyManager.getRestrictBackground());
|
|
||||||
|
|
||||||
// TODO: Define behavior of this sync button. See: http://b/16076571
|
|
||||||
mMenuAutoSync = menu.findItem(R.id.data_usage_menu_auto_sync);
|
|
||||||
mMenuAutoSync.setChecked(ContentResolver.getMasterSyncAutomatically());
|
|
||||||
mMenuAutoSync.setVisible(!appDetailMode);
|
|
||||||
|
|
||||||
final MenuItem split4g = menu.findItem(R.id.data_usage_menu_split_4g);
|
|
||||||
split4g.setVisible(hasReadyMobile4gRadio(context) && isOwner && !appDetailMode);
|
|
||||||
split4g.setChecked(isMobilePolicySplit());
|
|
||||||
|
|
||||||
final MenuItem showWifi = menu.findItem(R.id.data_usage_menu_show_wifi);
|
|
||||||
if (hasWifiRadio(context) && hasReadyMobileRadio(context)) {
|
|
||||||
showWifi.setVisible(!appDetailMode);
|
|
||||||
showWifi.setChecked(mShowWifi);
|
|
||||||
} else {
|
|
||||||
showWifi.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
final MenuItem showEthernet = menu.findItem(R.id.data_usage_menu_show_ethernet);
|
|
||||||
if (hasEthernet(context) && hasReadyMobileRadio(context)) {
|
|
||||||
showEthernet.setVisible(!appDetailMode);
|
|
||||||
showEthernet.setChecked(mShowEthernet);
|
|
||||||
} else {
|
|
||||||
showEthernet.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
|
final MenuItem metered = menu.findItem(R.id.data_usage_menu_metered);
|
||||||
if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
|
if (hasReadyMobileRadio(context) || hasWifiRadio(context)) {
|
||||||
@@ -521,6 +510,17 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
metered.setVisible(false);
|
metered.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: show when multiple sims available
|
||||||
|
mMenuSimCards = menu.findItem(R.id.data_usage_menu_sim_cards);
|
||||||
|
mMenuSimCards.setVisible(false);
|
||||||
|
|
||||||
|
mMenuCellularNetworks = menu.findItem(R.id.data_usage_menu_cellular_networks);
|
||||||
|
if (hasReadyMobileRadio(context)) {
|
||||||
|
mMenuCellularNetworks.setVisible(!appDetailMode);
|
||||||
|
} else {
|
||||||
|
mMenuCellularNetworks.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
final MenuItem help = menu.findItem(R.id.data_usage_menu_help);
|
final MenuItem help = menu.findItem(R.id.data_usage_menu_help);
|
||||||
String helpUrl;
|
String helpUrl;
|
||||||
if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_data_usage))) {
|
if (!TextUtils.isEmpty(helpUrl = getResources().getString(R.string.help_url_data_usage))) {
|
||||||
@@ -528,23 +528,35 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
} else {
|
} else {
|
||||||
help.setVisible(false);
|
help.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMenuTitles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMenuTitles() {
|
||||||
|
if (mPolicyManager.getRestrictBackground()) {
|
||||||
|
mMenuRestrictBackground.setTitle(R.string.data_usage_menu_allow_background);
|
||||||
|
} else {
|
||||||
|
mMenuRestrictBackground.setTitle(R.string.data_usage_menu_restrict_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShowWifi) {
|
||||||
|
mMenuShowWifi.setTitle(R.string.data_usage_menu_hide_wifi);
|
||||||
|
} else {
|
||||||
|
mMenuShowWifi.setTitle(R.string.data_usage_menu_show_wifi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShowEthernet) {
|
||||||
|
mMenuShowEthernet.setTitle(R.string.data_usage_menu_hide_ethernet);
|
||||||
|
} else {
|
||||||
|
mMenuShowEthernet.setTitle(R.string.data_usage_menu_show_ethernet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.data_usage_menu_roaming: {
|
|
||||||
final boolean dataRoaming = !item.isChecked();
|
|
||||||
if (dataRoaming) {
|
|
||||||
ConfirmDataRoamingFragment.show(this);
|
|
||||||
} else {
|
|
||||||
// no confirmation to disable roaming
|
|
||||||
setDataRoaming(false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case R.id.data_usage_menu_restrict_background: {
|
case R.id.data_usage_menu_restrict_background: {
|
||||||
final boolean restrictBackground = !item.isChecked();
|
final boolean restrictBackground = !mPolicyManager.getRestrictBackground();
|
||||||
if (restrictBackground) {
|
if (restrictBackground) {
|
||||||
ConfirmRestrictFragment.show(this);
|
ConfirmRestrictFragment.show(this);
|
||||||
} else {
|
} else {
|
||||||
@@ -553,41 +565,37 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.data_usage_menu_split_4g: {
|
|
||||||
final boolean mobileSplit = !item.isChecked();
|
|
||||||
setMobilePolicySplit(mobileSplit);
|
|
||||||
item.setChecked(isMobilePolicySplit());
|
|
||||||
updateTabs();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case R.id.data_usage_menu_show_wifi: {
|
case R.id.data_usage_menu_show_wifi: {
|
||||||
mShowWifi = !item.isChecked();
|
mShowWifi = !mShowWifi;
|
||||||
mPrefs.edit().putBoolean(PREF_SHOW_WIFI, mShowWifi).apply();
|
mPrefs.edit().putBoolean(PREF_SHOW_WIFI, mShowWifi).apply();
|
||||||
item.setChecked(mShowWifi);
|
updateMenuTitles();
|
||||||
updateTabs();
|
updateTabs();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.data_usage_menu_show_ethernet: {
|
case R.id.data_usage_menu_show_ethernet: {
|
||||||
mShowEthernet = !item.isChecked();
|
mShowEthernet = !mShowEthernet;
|
||||||
mPrefs.edit().putBoolean(PREF_SHOW_ETHERNET, mShowEthernet).apply();
|
mPrefs.edit().putBoolean(PREF_SHOW_ETHERNET, mShowEthernet).apply();
|
||||||
item.setChecked(mShowEthernet);
|
updateMenuTitles();
|
||||||
updateTabs();
|
updateTabs();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case R.id.data_usage_menu_sim_cards: {
|
||||||
|
// TODO: hook up to sim cards
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case R.id.data_usage_menu_cellular_networks: {
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||||
|
intent.setComponent(new ComponentName("com.android.phone",
|
||||||
|
"com.android.phone.MobileNetworkSettings"));
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case R.id.data_usage_menu_metered: {
|
case R.id.data_usage_menu_metered: {
|
||||||
final SettingsActivity sa = (SettingsActivity) getActivity();
|
final SettingsActivity sa = (SettingsActivity) getActivity();
|
||||||
sa.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
|
sa.startPreferencePanel(DataUsageMeteredSettings.class.getCanonicalName(), null,
|
||||||
R.string.data_usage_metered_title, null, this, 0);
|
R.string.data_usage_metered_title, null, this, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.data_usage_menu_auto_sync: {
|
|
||||||
if (ActivityManager.isUserAMonkey()) {
|
|
||||||
Log.d("SyncState", "ignoring monkey's attempt to flip global sync state");
|
|
||||||
} else {
|
|
||||||
ConfirmAutoSyncChangeFragment.show(this, !item.isChecked());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -725,7 +733,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
|
if (LOGD) Log.d(TAG, "updateBody() with currentTab=" + currentTab);
|
||||||
|
|
||||||
mDataEnabledView.setVisibility(isOwner ? View.VISIBLE : View.GONE);
|
mDataEnabledSupported = isOwner;
|
||||||
|
mDisableAtLimitSupported = true;
|
||||||
|
|
||||||
// TODO: remove mobile tabs when SIM isn't ready
|
// TODO: remove mobile tabs when SIM isn't ready
|
||||||
|
|
||||||
@@ -748,14 +757,14 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
} else if (TAB_WIFI.equals(currentTab)) {
|
} else if (TAB_WIFI.equals(currentTab)) {
|
||||||
// wifi doesn't have any controls
|
// wifi doesn't have any controls
|
||||||
mDataEnabledView.setVisibility(View.GONE);
|
mDataEnabledSupported = false;
|
||||||
mDisableAtLimitView.setVisibility(View.GONE);
|
mDisableAtLimitSupported = false;
|
||||||
mTemplate = buildTemplateWifiWildcard();
|
mTemplate = buildTemplateWifiWildcard();
|
||||||
|
|
||||||
} else if (TAB_ETHERNET.equals(currentTab)) {
|
} else if (TAB_ETHERNET.equals(currentTab)) {
|
||||||
// ethernet doesn't have any controls
|
// ethernet doesn't have any controls
|
||||||
mDataEnabledView.setVisibility(View.GONE);
|
mDataEnabledSupported = false;
|
||||||
mDisableAtLimitView.setVisibility(View.GONE);
|
mDisableAtLimitSupported = false;
|
||||||
mTemplate = buildTemplateEthernet();
|
mTemplate = buildTemplateEthernet();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -808,12 +817,25 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
mAppIcon.setImageDrawable(detail.icon);
|
mAppIcon.setImageDrawable(detail.icon);
|
||||||
|
|
||||||
mAppTitles.removeAllViews();
|
mAppTitles.removeAllViews();
|
||||||
|
|
||||||
|
View title = null;
|
||||||
if (detail.detailLabels != null) {
|
if (detail.detailLabels != null) {
|
||||||
for (CharSequence label : detail.detailLabels) {
|
for (CharSequence label : detail.detailLabels) {
|
||||||
mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, label));
|
title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
|
||||||
|
((TextView) title.findViewById(R.id.app_title)).setText(label);
|
||||||
|
mAppTitles.addView(title);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mAppTitles.addView(inflateAppTitle(inflater, mAppTitles, detail.label));
|
title = inflater.inflate(R.layout.data_usage_app_title, mAppTitles, false);
|
||||||
|
((TextView) title.findViewById(R.id.app_title)).setText(detail.label);
|
||||||
|
mAppTitles.addView(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember last slot for summary
|
||||||
|
if (title != null) {
|
||||||
|
mAppTotal = (TextView) title.findViewById(R.id.app_summary);
|
||||||
|
} else {
|
||||||
|
mAppTotal = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable settings button when package provides it
|
// enable settings button when package provides it
|
||||||
@@ -904,24 +926,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getDataRoaming() {
|
|
||||||
final ContentResolver resolver = getActivity().getContentResolver();
|
|
||||||
return android.provider.Settings.Global.getInt(resolver,
|
|
||||||
android.provider.Settings.Global.DATA_ROAMING, 0) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDataRoaming(boolean enabled) {
|
|
||||||
// TODO: teach telephony DataConnectionTracker to watch and apply
|
|
||||||
// updates when changed.
|
|
||||||
final ContentResolver resolver = getActivity().getContentResolver();
|
|
||||||
android.provider.Settings.Global.putInt(resolver,
|
|
||||||
android.provider.Settings.Global.DATA_ROAMING, enabled ? 1 : 0);
|
|
||||||
mMenuDataRoaming.setChecked(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRestrictBackground(boolean restrictBackground) {
|
public void setRestrictBackground(boolean restrictBackground) {
|
||||||
mPolicyManager.setRestrictBackground(restrictBackground);
|
mPolicyManager.setRestrictBackground(restrictBackground);
|
||||||
mMenuRestrictBackground.setChecked(restrictBackground);
|
updateMenuTitles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getAppRestrictBackground() {
|
private boolean getAppRestrictBackground() {
|
||||||
@@ -943,10 +950,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
* current {@link #mTemplate}.
|
* current {@link #mTemplate}.
|
||||||
*/
|
*/
|
||||||
private void updatePolicy(boolean refreshCycle) {
|
private void updatePolicy(boolean refreshCycle) {
|
||||||
|
boolean dataEnabledVisible = mDataEnabledSupported;
|
||||||
|
boolean disableAtLimitVisible = mDisableAtLimitSupported;
|
||||||
|
|
||||||
if (isAppDetailMode()) {
|
if (isAppDetailMode()) {
|
||||||
mNetworkSwitches.setVisibility(View.GONE);
|
dataEnabledVisible = false;
|
||||||
} else {
|
disableAtLimitVisible = false;
|
||||||
mNetworkSwitches.setVisibility(View.VISIBLE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move enabled state directly into policy
|
// TODO: move enabled state directly into policy
|
||||||
@@ -958,7 +967,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
|
final NetworkPolicy policy = mPolicyEditor.getPolicy(mTemplate);
|
||||||
if (isNetworkPolicyModifiable(policy)) {
|
if (isNetworkPolicyModifiable(policy)) {
|
||||||
mDisableAtLimitView.setVisibility(View.VISIBLE);
|
|
||||||
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
|
mDisableAtLimit.setChecked(policy != null && policy.limitBytes != LIMIT_DISABLED);
|
||||||
if (!isAppDetailMode()) {
|
if (!isAppDetailMode()) {
|
||||||
mChart.bindNetworkPolicy(policy);
|
mChart.bindNetworkPolicy(policy);
|
||||||
@@ -966,10 +974,13 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// controls are disabled; don't bind warning/limit sweeps
|
// controls are disabled; don't bind warning/limit sweeps
|
||||||
mDisableAtLimitView.setVisibility(View.GONE);
|
disableAtLimitVisible = false;
|
||||||
mChart.bindNetworkPolicy(null);
|
mChart.bindNetworkPolicy(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDataEnabledView.setVisibility(dataEnabledVisible ? View.VISIBLE : View.GONE);
|
||||||
|
mDisableAtLimitView.setVisibility(disableAtLimitVisible ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if (refreshCycle) {
|
if (refreshCycle) {
|
||||||
// generate cycle list based on policy and available history
|
// generate cycle list based on policy and available history
|
||||||
updateCycleList(policy);
|
updateCycleList(policy);
|
||||||
@@ -1049,12 +1060,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnCheckedChangeListener mDataEnabledListener = new OnCheckedChangeListener() {
|
private View.OnClickListener mDataEnabledListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
public void onClick(View v) {
|
||||||
if (mBinding) return;
|
if (mBinding) return;
|
||||||
|
|
||||||
final boolean dataEnabled = isChecked;
|
final boolean dataEnabled = !mDataEnabled.isChecked();
|
||||||
final String currentTab = mCurrentTab;
|
final String currentTab = mCurrentTab;
|
||||||
if (TAB_MOBILE.equals(currentTab)) {
|
if (TAB_MOBILE.equals(currentTab)) {
|
||||||
if (dataEnabled) {
|
if (dataEnabled) {
|
||||||
@@ -1178,15 +1189,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
final long defaultBytes = entry.rxBytes + entry.txBytes;
|
final long defaultBytes = entry.rxBytes + entry.txBytes;
|
||||||
entry = mChartData.detailForeground.getValues(start, end, now, entry);
|
entry = mChartData.detailForeground.getValues(start, end, now, entry);
|
||||||
final long foregroundBytes = entry.rxBytes + entry.txBytes;
|
final long foregroundBytes = entry.rxBytes + entry.txBytes;
|
||||||
|
final long totalBytes = defaultBytes + foregroundBytes;
|
||||||
|
|
||||||
mAppPieChart.setOriginAngle(175);
|
if (mAppTotal != null) {
|
||||||
|
mAppTotal.setText(Formatter.formatFileSize(context, totalBytes));
|
||||||
mAppPieChart.removeAllSlices();
|
}
|
||||||
mAppPieChart.addSlice(foregroundBytes, FOREGROUND_BYTES_COLOR);
|
|
||||||
mAppPieChart.addSlice(defaultBytes, DEFAULT_BYTES_COLOR);
|
|
||||||
|
|
||||||
mAppPieChart.generatePath();
|
|
||||||
|
|
||||||
mAppBackground.setText(Formatter.formatFileSize(context, defaultBytes));
|
mAppBackground.setText(Formatter.formatFileSize(context, defaultBytes));
|
||||||
mAppForeground.setText(Formatter.formatFileSize(context, foregroundBytes));
|
mAppForeground.setText(Formatter.formatFileSize(context, foregroundBytes));
|
||||||
|
|
||||||
@@ -1195,11 +1202,15 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
getLoaderManager().destroyLoader(LOADER_SUMMARY);
|
getLoaderManager().destroyLoader(LOADER_SUMMARY);
|
||||||
|
|
||||||
|
mCycleSummary.setVisibility(View.GONE);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (mChartData != null) {
|
if (mChartData != null) {
|
||||||
entry = mChartData.network.getValues(start, end, now, null);
|
entry = mChartData.network.getValues(start, end, now, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCycleSummary.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// kick off loader for detailed stats
|
// kick off loader for detailed stats
|
||||||
getLoaderManager().restartLoader(LOADER_SUMMARY,
|
getLoaderManager().restartLoader(LOADER_SUMMARY,
|
||||||
SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryCallbacks);
|
SummaryForAllUidLoader.buildArgs(mTemplate, start, end), mSummaryCallbacks);
|
||||||
@@ -1207,17 +1218,18 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
|
final long totalBytes = entry != null ? entry.rxBytes + entry.txBytes : 0;
|
||||||
final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
|
final String totalPhrase = Formatter.formatFileSize(context, totalBytes);
|
||||||
final String rangePhrase = formatDateRange(context, start, end);
|
mCycleSummary.setText(totalPhrase);
|
||||||
|
|
||||||
final int summaryRes;
|
|
||||||
if (TAB_MOBILE.equals(mCurrentTab) || TAB_3G.equals(mCurrentTab)
|
if (TAB_MOBILE.equals(mCurrentTab) || TAB_3G.equals(mCurrentTab)
|
||||||
|| TAB_4G.equals(mCurrentTab)) {
|
|| TAB_4G.equals(mCurrentTab)) {
|
||||||
summaryRes = R.string.data_usage_total_during_range_mobile;
|
if (isAppDetailMode()) {
|
||||||
|
mDisclaimer.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
summaryRes = R.string.data_usage_total_during_range;
|
mDisclaimer.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mDisclaimer.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUsageSummary.setText(getString(summaryRes, totalPhrase, rangePhrase));
|
|
||||||
|
|
||||||
// initial layout is finished above, ensure we have transitions
|
// initial layout is finished above, ensure we have transitions
|
||||||
ensureLayoutTransitions();
|
ensureLayoutTransitions();
|
||||||
@@ -1278,6 +1290,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
private void updateEmptyVisible() {
|
private void updateEmptyVisible() {
|
||||||
final boolean isEmpty = mAdapter.isEmpty() && !isAppDetailMode();
|
final boolean isEmpty = mAdapter.isEmpty() && !isAppDetailMode();
|
||||||
mEmpty.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
mEmpty.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||||
|
mStupidPadding.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1308,12 +1321,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DataUsageChartListener mChartListener = new DataUsageChartListener() {
|
private DataUsageChartListener mChartListener = new DataUsageChartListener() {
|
||||||
@Override
|
|
||||||
public void onInspectRangeChanged() {
|
|
||||||
if (LOGD) Log.d(TAG, "onInspectRangeChanged()");
|
|
||||||
updateDetailData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWarningChanged() {
|
public void onWarningChanged() {
|
||||||
setPolicyWarningBytes(mChart.getWarningBytes());
|
setPolicyWarningBytes(mChart.getWarningBytes());
|
||||||
@@ -1404,8 +1411,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
private final CycleChangeItem mChangeItem;
|
private final CycleChangeItem mChangeItem;
|
||||||
|
|
||||||
public CycleAdapter(Context context) {
|
public CycleAdapter(Context context) {
|
||||||
super(context, android.R.layout.simple_spinner_item);
|
super(context, R.layout.data_usage_cycle_item);
|
||||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
setDropDownViewResource(R.layout.data_usage_cycle_item_dropdown);
|
||||||
mChangeItem = new CycleChangeItem(context);
|
mChangeItem = new CycleChangeItem(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1447,11 +1454,21 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class AppItem implements Comparable<AppItem>, Parcelable {
|
public static class AppItem implements Comparable<AppItem>, Parcelable {
|
||||||
|
public static final int CATEGORY_USER = 0;
|
||||||
|
public static final int CATEGORY_APP_TITLE = 1;
|
||||||
|
public static final int CATEGORY_APP = 2;
|
||||||
|
|
||||||
public final int key;
|
public final int key;
|
||||||
public boolean restricted;
|
public boolean restricted;
|
||||||
|
public int category;
|
||||||
|
|
||||||
public SparseBooleanArray uids = new SparseBooleanArray();
|
public SparseBooleanArray uids = new SparseBooleanArray();
|
||||||
public long total;
|
public long total;
|
||||||
|
|
||||||
|
public AppItem() {
|
||||||
|
this.key = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public AppItem(int key) {
|
public AppItem(int key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
@@ -1480,7 +1497,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(AppItem another) {
|
public int compareTo(AppItem another) {
|
||||||
return Long.compare(another.total, total);
|
int comparison = Integer.compare(another.category, category);
|
||||||
|
if (comparison == 0) {
|
||||||
|
comparison = Long.compare(another.total, total);
|
||||||
|
}
|
||||||
|
return comparison;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<AppItem> CREATOR = new Creator<AppItem>() {
|
public static final Creator<AppItem> CREATOR = new Creator<AppItem>() {
|
||||||
@@ -1516,9 +1537,11 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
*/
|
*/
|
||||||
public void bindStats(NetworkStats stats, int[] restrictedUids) {
|
public void bindStats(NetworkStats stats, int[] restrictedUids) {
|
||||||
mItems.clear();
|
mItems.clear();
|
||||||
|
mLargest = 0;
|
||||||
|
|
||||||
final int currentUserId = ActivityManager.getCurrentUser();
|
final int currentUserId = ActivityManager.getCurrentUser();
|
||||||
final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
|
final SparseArray<AppItem> knownItems = new SparseArray<AppItem>();
|
||||||
|
boolean hasApps = false;
|
||||||
|
|
||||||
NetworkStats.Entry entry = null;
|
NetworkStats.Entry entry = null;
|
||||||
final int size = stats != null ? stats.size() : 0;
|
final int size = stats != null ? stats.size() : 0;
|
||||||
@@ -1548,6 +1571,9 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
item.addUid(uid);
|
item.addUid(uid);
|
||||||
item.total += entry.rxBytes + entry.txBytes;
|
item.total += entry.rxBytes + entry.txBytes;
|
||||||
|
if (item.total > mLargest) {
|
||||||
|
mLargest = item.total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int uid : restrictedUids) {
|
for (int uid : restrictedUids) {
|
||||||
@@ -1564,8 +1590,14 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
item.restricted = true;
|
item.restricted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasApps = !mItems.isEmpty();
|
||||||
|
if (hasApps) {
|
||||||
|
final AppItem title = new AppItem();
|
||||||
|
title.category = AppItem.CATEGORY_APP_TITLE;
|
||||||
|
mItems.add(title);
|
||||||
|
}
|
||||||
|
|
||||||
Collections.sort(mItems);
|
Collections.sort(mItems);
|
||||||
mLargest = (mItems.size() > 0) ? mItems.get(0).total : 0;
|
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1584,8 +1616,44 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
return mItems.get(position).key;
|
return mItems.get(position).key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getViewTypeCount() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
final AppItem item = mItems.get(position);
|
||||||
|
if (item.category == AppItem.CATEGORY_APP_TITLE) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areAllItemsEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(int position) {
|
||||||
|
return getItemViewType(position) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
final AppItem item = mItems.get(position);
|
||||||
|
if (getItemViewType(position) == 1) {
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = inflateCategoryHeader(LayoutInflater.from(parent.getContext()),
|
||||||
|
parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
|
||||||
|
title.setText(R.string.data_usage_app);
|
||||||
|
|
||||||
|
} else {
|
||||||
if (convertView == null) {
|
if (convertView == null) {
|
||||||
convertView = LayoutInflater.from(parent.getContext()).inflate(
|
convertView = LayoutInflater.from(parent.getContext()).inflate(
|
||||||
R.layout.data_usage_item, parent, false);
|
R.layout.data_usage_item, parent, false);
|
||||||
@@ -1602,7 +1670,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
android.R.id.progress);
|
android.R.id.progress);
|
||||||
|
|
||||||
// kick off async load of app details
|
// kick off async load of app details
|
||||||
final AppItem item = mItems.get(position);
|
|
||||||
UidDetailTask.bindView(mProvider, item, convertView);
|
UidDetailTask.bindView(mProvider, item, convertView);
|
||||||
|
|
||||||
if (item.restricted && item.total <= 0) {
|
if (item.restricted && item.total <= 0) {
|
||||||
@@ -1615,6 +1682,7 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
|
|
||||||
final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
|
final int percentTotal = mLargest != 0 ? (int) (item.total * 100 / mLargest) : 0;
|
||||||
progress.setProgress(percentTotal);
|
progress.setProgress(percentTotal);
|
||||||
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
@@ -1639,7 +1707,8 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
|
final FragmentTransaction ft = parent.getFragmentManager().beginTransaction();
|
||||||
ft.add(fragment, TAG_APP_DETAILS);
|
ft.add(fragment, TAG_APP_DETAILS);
|
||||||
ft.addToBackStack(TAG_APP_DETAILS);
|
ft.addToBackStack(TAG_APP_DETAILS);
|
||||||
ft.setBreadCrumbTitle(label);
|
ft.setBreadCrumbTitle(
|
||||||
|
parent.getResources().getString(R.string.data_usage_app_summary_title));
|
||||||
ft.commitAllowingStateLoss();
|
ft.commitAllowingStateLoss();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1946,46 +2015,6 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dialog to request user confirmation before setting
|
|
||||||
* {@link android.provider.Settings.Global#DATA_ROAMING}.
|
|
||||||
*/
|
|
||||||
public static class ConfirmDataRoamingFragment extends DialogFragment {
|
|
||||||
public static void show(DataUsageSummary parent) {
|
|
||||||
if (!parent.isAdded()) return;
|
|
||||||
|
|
||||||
final ConfirmDataRoamingFragment dialog = new ConfirmDataRoamingFragment();
|
|
||||||
dialog.setTargetFragment(parent, 0);
|
|
||||||
dialog.show(parent.getFragmentManager(), TAG_CONFIRM_DATA_ROAMING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
||||||
final Context context = getActivity();
|
|
||||||
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setTitle(R.string.roaming_reenable_title);
|
|
||||||
if (Utils.hasMultipleUsers(context)) {
|
|
||||||
builder.setMessage(R.string.roaming_warning_multiuser);
|
|
||||||
} else {
|
|
||||||
builder.setMessage(R.string.roaming_warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
final DataUsageSummary target = (DataUsageSummary) getTargetFragment();
|
|
||||||
if (target != null) {
|
|
||||||
target.setDataRoaming(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
|
|
||||||
return builder.create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog to request user confirmation before setting
|
* Dialog to request user confirmation before setting
|
||||||
* {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
|
* {@link INetworkPolicyManager#setRestrictBackground(boolean)}.
|
||||||
@@ -2308,12 +2337,12 @@ public class DataUsageSummary extends HighlightingFragment implements Indexable
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static View inflateAppTitle(
|
private static View inflateCategoryHeader(LayoutInflater inflater, ViewGroup root) {
|
||||||
LayoutInflater inflater, ViewGroup root, CharSequence label) {
|
final TypedArray a = inflater.getContext().obtainStyledAttributes(null,
|
||||||
final TextView view = (TextView) inflater.inflate(
|
com.android.internal.R.styleable.Preference,
|
||||||
R.layout.data_usage_app_title, root, false);
|
com.android.internal.R.attr.preferenceCategoryStyle, 0);
|
||||||
view.setText(label);
|
final int resId = a.getResourceId(com.android.internal.R.styleable.Preference_layout, 0);
|
||||||
return view;
|
return inflater.inflate(resId, root, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -29,10 +29,9 @@ import android.net.NetworkTemplate;
|
|||||||
import android.net.wifi.WifiConfiguration;
|
import android.net.wifi.WifiConfiguration;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
import android.provider.SearchIndexableResource;
|
import android.preference.SwitchPreference;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
@@ -42,7 +41,6 @@ import com.android.settings.search.Indexable;
|
|||||||
import com.android.settings.search.SearchIndexableRaw;
|
import com.android.settings.search.SearchIndexableRaw;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,7 +115,7 @@ public class DataUsageMeteredSettings extends SettingsPreferenceFragment impleme
|
|||||||
return pref;
|
return pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MeteredPreference extends CheckBoxPreference {
|
private class MeteredPreference extends SwitchPreference {
|
||||||
private final NetworkTemplate mTemplate;
|
private final NetworkTemplate mTemplate;
|
||||||
private boolean mBinding;
|
private boolean mBinding;
|
||||||
|
|
||||||
|
@@ -50,26 +50,24 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
private static final int MSG_UPDATE_AXIS = 100;
|
private static final int MSG_UPDATE_AXIS = 100;
|
||||||
private static final long DELAY_MILLIS = 250;
|
private static final long DELAY_MILLIS = 250;
|
||||||
|
|
||||||
private static final boolean LIMIT_SWEEPS_TO_VALID_DATA = false;
|
|
||||||
|
|
||||||
private ChartGridView mGrid;
|
private ChartGridView mGrid;
|
||||||
private ChartNetworkSeriesView mSeries;
|
private ChartNetworkSeriesView mSeries;
|
||||||
private ChartNetworkSeriesView mDetailSeries;
|
private ChartNetworkSeriesView mDetailSeries;
|
||||||
|
|
||||||
private NetworkStatsHistory mHistory;
|
private NetworkStatsHistory mHistory;
|
||||||
|
|
||||||
private ChartSweepView mSweepLeft;
|
|
||||||
private ChartSweepView mSweepRight;
|
|
||||||
private ChartSweepView mSweepWarning;
|
private ChartSweepView mSweepWarning;
|
||||||
private ChartSweepView mSweepLimit;
|
private ChartSweepView mSweepLimit;
|
||||||
|
|
||||||
|
private long mInspectStart;
|
||||||
|
private long mInspectEnd;
|
||||||
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
|
|
||||||
/** Current maximum value of {@link #mVert}. */
|
/** Current maximum value of {@link #mVert}. */
|
||||||
private long mVertMax;
|
private long mVertMax;
|
||||||
|
|
||||||
public interface DataUsageChartListener {
|
public interface DataUsageChartListener {
|
||||||
public void onInspectRangeChanged();
|
|
||||||
public void onWarningChanged();
|
public void onWarningChanged();
|
||||||
public void onLimitChanged();
|
public void onLimitChanged();
|
||||||
public void requestWarningEdit();
|
public void requestWarningEdit();
|
||||||
@@ -112,43 +110,27 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
mDetailSeries = (ChartNetworkSeriesView) findViewById(R.id.detail_series);
|
mDetailSeries = (ChartNetworkSeriesView) findViewById(R.id.detail_series);
|
||||||
mDetailSeries.setVisibility(View.GONE);
|
mDetailSeries.setVisibility(View.GONE);
|
||||||
|
|
||||||
mSweepLeft = (ChartSweepView) findViewById(R.id.sweep_left);
|
|
||||||
mSweepRight = (ChartSweepView) findViewById(R.id.sweep_right);
|
|
||||||
mSweepLimit = (ChartSweepView) findViewById(R.id.sweep_limit);
|
mSweepLimit = (ChartSweepView) findViewById(R.id.sweep_limit);
|
||||||
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
|
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
|
||||||
|
|
||||||
// prevent sweeps from crossing each other
|
// prevent sweeps from crossing each other
|
||||||
mSweepLeft.setValidRangeDynamic(null, mSweepRight);
|
|
||||||
mSweepRight.setValidRangeDynamic(mSweepLeft, null);
|
|
||||||
mSweepWarning.setValidRangeDynamic(null, mSweepLimit);
|
mSweepWarning.setValidRangeDynamic(null, mSweepLimit);
|
||||||
mSweepLimit.setValidRangeDynamic(mSweepWarning, null);
|
mSweepLimit.setValidRangeDynamic(mSweepWarning, null);
|
||||||
|
|
||||||
// mark neighbors for checking touch events against
|
// mark neighbors for checking touch events against
|
||||||
mSweepLeft.setNeighbors(mSweepRight);
|
mSweepLimit.setNeighbors(mSweepWarning);
|
||||||
mSweepRight.setNeighbors(mSweepLeft);
|
mSweepWarning.setNeighbors(mSweepLimit);
|
||||||
mSweepLimit.setNeighbors(mSweepWarning, mSweepLeft, mSweepRight);
|
|
||||||
mSweepWarning.setNeighbors(mSweepLimit, mSweepLeft, mSweepRight);
|
|
||||||
|
|
||||||
mSweepLeft.addOnSweepListener(mHorizListener);
|
|
||||||
mSweepRight.addOnSweepListener(mHorizListener);
|
|
||||||
mSweepWarning.addOnSweepListener(mVertListener);
|
mSweepWarning.addOnSweepListener(mVertListener);
|
||||||
mSweepLimit.addOnSweepListener(mVertListener);
|
mSweepLimit.addOnSweepListener(mVertListener);
|
||||||
|
|
||||||
mSweepWarning.setDragInterval(5 * MB_IN_BYTES);
|
mSweepWarning.setDragInterval(5 * MB_IN_BYTES);
|
||||||
mSweepLimit.setDragInterval(5 * MB_IN_BYTES);
|
mSweepLimit.setDragInterval(5 * MB_IN_BYTES);
|
||||||
|
|
||||||
// TODO: make time sweeps adjustable through dpad
|
|
||||||
mSweepLeft.setClickable(false);
|
|
||||||
mSweepLeft.setFocusable(false);
|
|
||||||
mSweepRight.setClickable(false);
|
|
||||||
mSweepRight.setFocusable(false);
|
|
||||||
|
|
||||||
// tell everyone about our axis
|
// tell everyone about our axis
|
||||||
mGrid.init(mHoriz, mVert);
|
mGrid.init(mHoriz, mVert);
|
||||||
mSeries.init(mHoriz, mVert);
|
mSeries.init(mHoriz, mVert);
|
||||||
mDetailSeries.init(mHoriz, mVert);
|
mDetailSeries.init(mHoriz, mVert);
|
||||||
mSweepLeft.init(mHoriz);
|
|
||||||
mSweepRight.init(mHoriz);
|
|
||||||
mSweepWarning.init(mVert);
|
mSweepWarning.init(mVert);
|
||||||
mSweepLimit.init(mVert);
|
mSweepLimit.init(mVert);
|
||||||
|
|
||||||
@@ -194,7 +176,7 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
mSweepLimit.setEnabled(true);
|
mSweepLimit.setEnabled(true);
|
||||||
mSweepLimit.setValue(policy.limitBytes);
|
mSweepLimit.setValue(policy.limitBytes);
|
||||||
} else {
|
} else {
|
||||||
mSweepLimit.setVisibility(View.VISIBLE);
|
mSweepLimit.setVisibility(View.INVISIBLE);
|
||||||
mSweepLimit.setEnabled(false);
|
mSweepLimit.setEnabled(false);
|
||||||
mSweepLimit.setValue(-1);
|
mSweepLimit.setValue(-1);
|
||||||
}
|
}
|
||||||
@@ -295,23 +277,6 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
mSeries.setEstimateVisible(estimateVisible);
|
mSeries.setEstimateVisible(estimateVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnSweepListener mHorizListener = new OnSweepListener() {
|
|
||||||
@Override
|
|
||||||
public void onSweep(ChartSweepView sweep, boolean sweepDone) {
|
|
||||||
updatePrimaryRange();
|
|
||||||
|
|
||||||
// update detail list only when done sweeping
|
|
||||||
if (sweepDone && mListener != null) {
|
|
||||||
mListener.onInspectRangeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void requestEdit(ChartSweepView sweep) {
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private void sendUpdateAxisDelayed(ChartSweepView sweep, boolean force) {
|
private void sendUpdateAxisDelayed(ChartSweepView sweep, boolean force) {
|
||||||
if (force || !mHandler.hasMessages(MSG_UPDATE_AXIS, sweep)) {
|
if (force || !mHandler.hasMessages(MSG_UPDATE_AXIS, sweep)) {
|
||||||
mHandler.sendMessageDelayed(
|
mHandler.sendMessageDelayed(
|
||||||
@@ -369,11 +334,11 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getInspectStart() {
|
public long getInspectStart() {
|
||||||
return mSweepLeft.getValue();
|
return mInspectStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getInspectEnd() {
|
public long getInspectEnd() {
|
||||||
return mSweepRight.getValue();
|
return mInspectEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getWarningBytes() {
|
public long getWarningBytes() {
|
||||||
@@ -384,14 +349,6 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
return mSweepLimit.getLabelValue();
|
return mSweepLimit.getLabelValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getHistoryStart() {
|
|
||||||
return mHistory != null ? mHistory.getStart() : Long.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getHistoryEnd() {
|
|
||||||
return mHistory != null ? mHistory.getEnd() : Long.MIN_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the exact time range that should be displayed, updating how
|
* Set the exact time range that should be displayed, updating how
|
||||||
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
|
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
|
||||||
@@ -403,30 +360,8 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
mSeries.setBounds(visibleStart, visibleEnd);
|
mSeries.setBounds(visibleStart, visibleEnd);
|
||||||
mDetailSeries.setBounds(visibleStart, visibleEnd);
|
mDetailSeries.setBounds(visibleStart, visibleEnd);
|
||||||
|
|
||||||
final long historyStart = getHistoryStart();
|
mInspectStart = visibleStart;
|
||||||
final long historyEnd = getHistoryEnd();
|
mInspectEnd = visibleEnd;
|
||||||
|
|
||||||
final long validStart = historyStart == Long.MAX_VALUE ? visibleStart
|
|
||||||
: Math.max(visibleStart, historyStart);
|
|
||||||
final long validEnd = historyEnd == Long.MIN_VALUE ? visibleEnd
|
|
||||||
: Math.min(visibleEnd, historyEnd);
|
|
||||||
|
|
||||||
if (LIMIT_SWEEPS_TO_VALID_DATA) {
|
|
||||||
// prevent time sweeps from leaving valid data
|
|
||||||
mSweepLeft.setValidRange(validStart, validEnd);
|
|
||||||
mSweepRight.setValidRange(validStart, validEnd);
|
|
||||||
} else {
|
|
||||||
mSweepLeft.setValidRange(visibleStart, visibleEnd);
|
|
||||||
mSweepRight.setValidRange(visibleStart, visibleEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// default sweeps to last week of data
|
|
||||||
final long halfRange = (visibleEnd + visibleStart) / 2;
|
|
||||||
final long sweepMax = validEnd;
|
|
||||||
final long sweepMin = Math.max(visibleStart, (sweepMax - DateUtils.WEEK_IN_MILLIS));
|
|
||||||
|
|
||||||
mSweepLeft.setValue(sweepMin);
|
|
||||||
mSweepRight.setValue(sweepMax);
|
|
||||||
|
|
||||||
requestLayout();
|
requestLayout();
|
||||||
if (changed) {
|
if (changed) {
|
||||||
@@ -440,15 +375,11 @@ public class ChartDataUsageView extends ChartView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updatePrimaryRange() {
|
private void updatePrimaryRange() {
|
||||||
final long left = mSweepLeft.getValue();
|
|
||||||
final long right = mSweepRight.getValue();
|
|
||||||
|
|
||||||
// prefer showing primary range on detail series, when available
|
// prefer showing primary range on detail series, when available
|
||||||
if (mDetailSeries.getVisibility() == View.VISIBLE) {
|
if (mDetailSeries.getVisibility() == View.VISIBLE) {
|
||||||
mDetailSeries.setPrimaryRange(left, right);
|
mSeries.setSecondary(true);
|
||||||
mSeries.setPrimaryRange(0, 0);
|
|
||||||
} else {
|
} else {
|
||||||
mSeries.setPrimaryRange(left, right);
|
mSeries.setSecondary(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,22 +19,25 @@ package com.android.settings.widget;
|
|||||||
import static com.android.settings.DataUsageSummary.formatDateRange;
|
import static com.android.settings.DataUsageSummary.formatDateRange;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background of {@link ChartView} that renders grid lines as requested by
|
* Background of {@link ChartView} that renders grid lines as requested by
|
||||||
* {@link ChartAxis#getTickPoints()}.
|
* {@link ChartAxis#getTickPoints()}.
|
||||||
@@ -47,10 +50,13 @@ public class ChartGridView extends View {
|
|||||||
private Drawable mPrimary;
|
private Drawable mPrimary;
|
||||||
private Drawable mSecondary;
|
private Drawable mSecondary;
|
||||||
private Drawable mBorder;
|
private Drawable mBorder;
|
||||||
|
|
||||||
|
private int mLabelSize;
|
||||||
private int mLabelColor;
|
private int mLabelColor;
|
||||||
|
|
||||||
private Layout mLayoutStart;
|
private Layout mLabelStart;
|
||||||
private Layout mLayoutEnd;
|
private Layout mLabelMid;
|
||||||
|
private Layout mLabelEnd;
|
||||||
|
|
||||||
public ChartGridView(Context context) {
|
public ChartGridView(Context context) {
|
||||||
this(context, null, 0);
|
this(context, null, 0);
|
||||||
@@ -71,7 +77,17 @@ public class ChartGridView extends View {
|
|||||||
mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
|
mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
|
||||||
mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
|
mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
|
||||||
mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
|
mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
|
||||||
mLabelColor = a.getColor(R.styleable.ChartGridView_labelColor, Color.RED);
|
|
||||||
|
final int taId = a.getResourceId(R.styleable.ChartGridView_android_textAppearance, -1);
|
||||||
|
final TypedArray ta = context.obtainStyledAttributes(taId,
|
||||||
|
com.android.internal.R.styleable.TextAppearance);
|
||||||
|
mLabelSize = ta.getDimensionPixelSize(
|
||||||
|
com.android.internal.R.styleable.TextAppearance_textSize, 0);
|
||||||
|
ta.recycle();
|
||||||
|
|
||||||
|
final ColorStateList labelColor = a.getColorStateList(
|
||||||
|
R.styleable.ChartGridView_android_textColor);
|
||||||
|
mLabelColor = labelColor.getDefaultColor();
|
||||||
|
|
||||||
a.recycle();
|
a.recycle();
|
||||||
}
|
}
|
||||||
@@ -83,18 +99,21 @@ public class ChartGridView extends View {
|
|||||||
|
|
||||||
void setBounds(long start, long end) {
|
void setBounds(long start, long end) {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
mLayoutStart = makeLayout(formatDateRange(context, start, start));
|
final long mid = (start + end) / 2;
|
||||||
mLayoutEnd = makeLayout(formatDateRange(context, end, end));
|
mLabelStart = makeLabel(formatDateRange(context, start, start));
|
||||||
|
mLabelMid = makeLabel(formatDateRange(context, mid, mid));
|
||||||
|
mLabelEnd = makeLabel(formatDateRange(context, end, end));
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
final int width = getWidth();
|
final int width = getWidth();
|
||||||
final int height = getHeight();
|
final int height = getHeight() - getPaddingBottom();
|
||||||
|
|
||||||
final Drawable secondary = mSecondary;
|
final Drawable secondary = mSecondary;
|
||||||
final int secondaryHeight = mSecondary.getIntrinsicHeight();
|
if (secondary != null) {
|
||||||
|
final int secondaryHeight = secondary.getIntrinsicHeight();
|
||||||
|
|
||||||
final float[] vertTicks = mVert.getTickPoints();
|
final float[] vertTicks = mVert.getTickPoints();
|
||||||
for (float y : vertTicks) {
|
for (float y : vertTicks) {
|
||||||
@@ -102,10 +121,12 @@ public class ChartGridView extends View {
|
|||||||
secondary.setBounds(0, (int) y, width, bottom);
|
secondary.setBounds(0, (int) y, width, bottom);
|
||||||
secondary.draw(canvas);
|
secondary.draw(canvas);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Drawable primary = mPrimary;
|
final Drawable primary = mPrimary;
|
||||||
final int primaryWidth = mPrimary.getIntrinsicWidth();
|
if (primary != null) {
|
||||||
final int primaryHeight = mPrimary.getIntrinsicHeight();
|
final int primaryWidth = primary.getIntrinsicWidth();
|
||||||
|
final int primaryHeight = primary.getIntrinsicHeight();
|
||||||
|
|
||||||
final float[] horizTicks = mHoriz.getTickPoints();
|
final float[] horizTicks = mHoriz.getTickPoints();
|
||||||
for (float x : horizTicks) {
|
for (float x : horizTicks) {
|
||||||
@@ -113,41 +134,48 @@ public class ChartGridView extends View {
|
|||||||
primary.setBounds((int) x, 0, right, height);
|
primary.setBounds((int) x, 0, right, height);
|
||||||
primary.draw(canvas);
|
primary.draw(canvas);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mBorder.setBounds(0, 0, width, height);
|
mBorder.setBounds(0, 0, width, height);
|
||||||
mBorder.draw(canvas);
|
mBorder.draw(canvas);
|
||||||
|
|
||||||
final int padding = mLayoutStart != null ? mLayoutStart.getHeight() / 8 : 0;
|
final int padding = mLabelStart != null ? mLabelStart.getHeight() / 8 : 0;
|
||||||
|
|
||||||
final Layout start = mLayoutStart;
|
final Layout start = mLabelStart;
|
||||||
if (start != null) {
|
if (start != null) {
|
||||||
canvas.save();
|
final int saveCount = canvas.save();
|
||||||
canvas.translate(0, height + padding);
|
canvas.translate(0, height + padding);
|
||||||
start.draw(canvas);
|
start.draw(canvas);
|
||||||
canvas.restore();
|
canvas.restoreToCount(saveCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Layout end = mLayoutEnd;
|
final Layout mid = mLabelMid;
|
||||||
|
if (mid != null) {
|
||||||
|
final int saveCount = canvas.save();
|
||||||
|
canvas.translate((width - mid.getWidth()) / 2, height + padding);
|
||||||
|
mid.draw(canvas);
|
||||||
|
canvas.restoreToCount(saveCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Layout end = mLabelEnd;
|
||||||
if (end != null) {
|
if (end != null) {
|
||||||
canvas.save();
|
final int saveCount = canvas.save();
|
||||||
canvas.translate(width - end.getWidth(), height + padding);
|
canvas.translate(width - end.getWidth(), height + padding);
|
||||||
end.draw(canvas);
|
end.draw(canvas);
|
||||||
canvas.restore();
|
canvas.restoreToCount(saveCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Layout makeLayout(CharSequence text) {
|
private Layout makeLabel(CharSequence text) {
|
||||||
final Resources res = getResources();
|
final Resources res = getResources();
|
||||||
final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
paint.density = res.getDisplayMetrics().density;
|
paint.density = res.getDisplayMetrics().density;
|
||||||
paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
|
paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
|
||||||
paint.setColor(mLabelColor);
|
paint.setColor(mLabelColor);
|
||||||
paint.setTextSize(
|
paint.setTextSize(mLabelSize);
|
||||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, res.getDisplayMetrics()));
|
|
||||||
|
|
||||||
return new StaticLayout(text, paint,
|
return new StaticLayout(text, paint,
|
||||||
(int) Math.ceil(Layout.getDesiredWidth(text, paint)),
|
(int) Math.ceil(Layout.getDesiredWidth(text, paint)),
|
||||||
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
|
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -60,17 +60,17 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
private Path mPathFill;
|
private Path mPathFill;
|
||||||
private Path mPathEstimate;
|
private Path mPathEstimate;
|
||||||
|
|
||||||
|
private int mSafeRegion;
|
||||||
|
|
||||||
private long mStart;
|
private long mStart;
|
||||||
private long mEnd;
|
private long mEnd;
|
||||||
|
|
||||||
private long mPrimaryLeft;
|
|
||||||
private long mPrimaryRight;
|
|
||||||
|
|
||||||
/** Series will be extended to reach this end time. */
|
/** Series will be extended to reach this end time. */
|
||||||
private long mEndTime = Long.MIN_VALUE;
|
private long mEndTime = Long.MIN_VALUE;
|
||||||
|
|
||||||
private boolean mPathValid = false;
|
private boolean mPathValid = false;
|
||||||
private boolean mEstimateVisible = false;
|
private boolean mEstimateVisible = false;
|
||||||
|
private boolean mSecondary = false;
|
||||||
|
|
||||||
private long mMax;
|
private long mMax;
|
||||||
private long mMaxEstimate;
|
private long mMaxEstimate;
|
||||||
@@ -93,8 +93,11 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
|
final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
|
||||||
final int fillSecondary = a.getColor(
|
final int fillSecondary = a.getColor(
|
||||||
R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
|
R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
|
||||||
|
final int safeRegion = a.getDimensionPixelSize(
|
||||||
|
R.styleable.ChartNetworkSeriesView_safeRegion, 0);
|
||||||
|
|
||||||
setChartColor(stroke, fill, fillSecondary);
|
setChartColor(stroke, fill, fillSecondary);
|
||||||
|
setSafeRegion(safeRegion);
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
|
|
||||||
a.recycle();
|
a.recycle();
|
||||||
@@ -134,6 +137,10 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
|
mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSafeRegion(int safeRegion) {
|
||||||
|
mSafeRegion = safeRegion;
|
||||||
|
}
|
||||||
|
|
||||||
public void bindNetworkStats(NetworkStatsHistory stats) {
|
public void bindNetworkStats(NetworkStatsHistory stats) {
|
||||||
mStats = stats;
|
mStats = stats;
|
||||||
invalidatePath();
|
invalidatePath();
|
||||||
@@ -145,14 +152,8 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
mEnd = end;
|
mEnd = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setSecondary(boolean secondary) {
|
||||||
* Set the range to paint with {@link #mPaintFill}, leaving the remaining
|
mSecondary = secondary;
|
||||||
* area to be painted with {@link #mPaintFillSecondary}.
|
|
||||||
*/
|
|
||||||
public void setPrimaryRange(long left, long right) {
|
|
||||||
mPrimaryLeft = left;
|
|
||||||
mPrimaryRight = right;
|
|
||||||
invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidatePath() {
|
public void invalidatePath() {
|
||||||
@@ -322,9 +323,6 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
generatePath();
|
generatePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
|
|
||||||
final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);
|
|
||||||
|
|
||||||
if (mEstimateVisible) {
|
if (mEstimateVisible) {
|
||||||
save = canvas.save();
|
save = canvas.save();
|
||||||
canvas.clipRect(0, 0, getWidth(), getHeight());
|
canvas.clipRect(0, 0, getWidth(), getHeight());
|
||||||
@@ -332,21 +330,11 @@ public class ChartNetworkSeriesView extends View {
|
|||||||
canvas.restoreToCount(save);
|
canvas.restoreToCount(save);
|
||||||
}
|
}
|
||||||
|
|
||||||
save = canvas.save();
|
final Paint paintFill = mSecondary ? mPaintFillSecondary : mPaintFill;
|
||||||
canvas.clipRect(0, 0, primaryLeftPoint, getHeight());
|
|
||||||
canvas.drawPath(mPathFill, mPaintFillSecondary);
|
|
||||||
canvas.restoreToCount(save);
|
|
||||||
|
|
||||||
save = canvas.save();
|
save = canvas.save();
|
||||||
canvas.clipRect(primaryRightPoint, 0, getWidth(), getHeight());
|
canvas.clipRect(mSafeRegion, 0, getWidth(), getHeight() - mSafeRegion);
|
||||||
canvas.drawPath(mPathFill, mPaintFillSecondary);
|
canvas.drawPath(mPathFill, paintFill);
|
||||||
canvas.restoreToCount(save);
|
canvas.restoreToCount(save);
|
||||||
|
|
||||||
save = canvas.save();
|
|
||||||
canvas.clipRect(primaryLeftPoint, 0, primaryRightPoint, getHeight());
|
|
||||||
canvas.drawPath(mPathFill, mPaintFill);
|
|
||||||
canvas.drawPath(mPathStroke, mPaintStroke);
|
|
||||||
canvas.restoreToCount(save);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,7 @@ public class ChartSweepView extends View {
|
|||||||
|
|
||||||
private Rect mMargins = new Rect();
|
private Rect mMargins = new Rect();
|
||||||
private float mNeighborMargin;
|
private float mNeighborMargin;
|
||||||
|
private int mSafeRegion;
|
||||||
|
|
||||||
private int mFollowAxis;
|
private int mFollowAxis;
|
||||||
|
|
||||||
@@ -125,6 +126,7 @@ public class ChartSweepView extends View {
|
|||||||
setSweepDrawable(a.getDrawable(R.styleable.ChartSweepView_sweepDrawable));
|
setSweepDrawable(a.getDrawable(R.styleable.ChartSweepView_sweepDrawable));
|
||||||
setFollowAxis(a.getInt(R.styleable.ChartSweepView_followAxis, -1));
|
setFollowAxis(a.getInt(R.styleable.ChartSweepView_followAxis, -1));
|
||||||
setNeighborMargin(a.getDimensionPixelSize(R.styleable.ChartSweepView_neighborMargin, 0));
|
setNeighborMargin(a.getDimensionPixelSize(R.styleable.ChartSweepView_neighborMargin, 0));
|
||||||
|
setSafeRegion(a.getDimensionPixelSize(R.styleable.ChartSweepView_safeRegion, 0));
|
||||||
|
|
||||||
setLabelMinSize(a.getDimensionPixelSize(R.styleable.ChartSweepView_labelSize, 0));
|
setLabelMinSize(a.getDimensionPixelSize(R.styleable.ChartSweepView_labelSize, 0));
|
||||||
setLabelTemplate(a.getResourceId(R.styleable.ChartSweepView_labelTemplate, 0));
|
setLabelTemplate(a.getResourceId(R.styleable.ChartSweepView_labelTemplate, 0));
|
||||||
@@ -259,7 +261,6 @@ public class ChartSweepView extends View {
|
|||||||
paint.density = getResources().getDisplayMetrics().density;
|
paint.density = getResources().getDisplayMetrics().density;
|
||||||
paint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
|
paint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
|
||||||
paint.setColor(mLabelColor);
|
paint.setColor(mLabelColor);
|
||||||
paint.setShadowLayer(4 * paint.density, 0, 0, Color.BLACK);
|
|
||||||
|
|
||||||
mLabelTemplate = new SpannableStringBuilder(template);
|
mLabelTemplate = new SpannableStringBuilder(template);
|
||||||
mLabelLayout = new DynamicLayout(
|
mLabelLayout = new DynamicLayout(
|
||||||
@@ -383,6 +384,10 @@ public class ChartSweepView extends View {
|
|||||||
mNeighborMargin = neighborMargin;
|
mNeighborMargin = neighborMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSafeRegion(int safeRegion) {
|
||||||
|
mSafeRegion = safeRegion;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set valid range this sweep can move within, defined by the given
|
* Set valid range this sweep can move within, defined by the given
|
||||||
* {@link ChartSweepView}. The most restrictive combination of all valid
|
* {@link ChartSweepView}. The most restrictive combination of all valid
|
||||||
@@ -709,7 +714,7 @@ public class ChartSweepView extends View {
|
|||||||
mLabelLayout.draw(canvas);
|
mLabelLayout.draw(canvas);
|
||||||
}
|
}
|
||||||
canvas.restoreToCount(count);
|
canvas.restoreToCount(count);
|
||||||
labelSize = (int) mLabelSize;
|
labelSize = (int) mLabelSize + mSafeRegion;
|
||||||
} else {
|
} else {
|
||||||
labelSize = 0;
|
labelSize = 0;
|
||||||
}
|
}
|
||||||
|
@@ -112,12 +112,18 @@ public class ChartView extends FrameLayout {
|
|||||||
|
|
||||||
parentRect.set(mContent);
|
parentRect.set(mContent);
|
||||||
|
|
||||||
if (child instanceof ChartNetworkSeriesView || child instanceof ChartGridView) {
|
if (child instanceof ChartNetworkSeriesView) {
|
||||||
// series are always laid out to fill entire graph area
|
// series are always laid out to fill entire graph area
|
||||||
// TODO: handle scrolling for series larger than content area
|
// TODO: handle scrolling for series larger than content area
|
||||||
Gravity.apply(params.gravity, width, height, parentRect, childRect);
|
Gravity.apply(params.gravity, width, height, parentRect, childRect);
|
||||||
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
|
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
|
||||||
|
|
||||||
|
} else if (child instanceof ChartGridView) {
|
||||||
|
// Grid uses some extra room for labels
|
||||||
|
Gravity.apply(params.gravity, width, height, parentRect, childRect);
|
||||||
|
child.layout(childRect.left, childRect.top, childRect.right,
|
||||||
|
childRect.bottom + child.getPaddingBottom());
|
||||||
|
|
||||||
} else if (child instanceof ChartSweepView) {
|
} else if (child instanceof ChartSweepView) {
|
||||||
layoutSweep((ChartSweepView) child, parentRect, childRect);
|
layoutSweep((ChartSweepView) child, parentRect, childRect);
|
||||||
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
|
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
|
||||||
@@ -154,5 +160,4 @@ public class ChartView extends FrameLayout {
|
|||||||
parentRect, childRect);
|
parentRect, childRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,244 +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.widget;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Matrix;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Paint.Style;
|
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.Path.Direction;
|
|
||||||
import android.graphics.RadialGradient;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.graphics.Shader.TileMode;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.google.android.collect.Lists;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pie chart with multiple items.
|
|
||||||
*/
|
|
||||||
public class PieChartView extends View {
|
|
||||||
public static final String TAG = "PieChartView";
|
|
||||||
public static final boolean LOGD = false;
|
|
||||||
|
|
||||||
private static final boolean FILL_GRADIENT = false;
|
|
||||||
|
|
||||||
private ArrayList<Slice> mSlices = Lists.newArrayList();
|
|
||||||
|
|
||||||
private int mOriginAngle;
|
|
||||||
private Matrix mMatrix = new Matrix();
|
|
||||||
|
|
||||||
private Paint mPaintOutline = new Paint();
|
|
||||||
|
|
||||||
private Path mPathSide = new Path();
|
|
||||||
private Path mPathSideOutline = new Path();
|
|
||||||
|
|
||||||
private Path mPathOutline = new Path();
|
|
||||||
|
|
||||||
private int mSideWidth;
|
|
||||||
|
|
||||||
public class Slice {
|
|
||||||
public long value;
|
|
||||||
|
|
||||||
public Path path = new Path();
|
|
||||||
public Path pathSide = new Path();
|
|
||||||
public Path pathOutline = new Path();
|
|
||||||
|
|
||||||
public Paint paint;
|
|
||||||
|
|
||||||
public Slice(long value, int color) {
|
|
||||||
this.value = value;
|
|
||||||
this.paint = buildFillPaint(color, getResources());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public PieChartView(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PieChartView(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PieChartView(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
|
|
||||||
mPaintOutline.setColor(Color.BLACK);
|
|
||||||
mPaintOutline.setStyle(Style.STROKE);
|
|
||||||
mPaintOutline.setStrokeWidth(3f * getResources().getDisplayMetrics().density);
|
|
||||||
mPaintOutline.setAntiAlias(true);
|
|
||||||
|
|
||||||
mSideWidth = (int) (20 * getResources().getDisplayMetrics().density);
|
|
||||||
|
|
||||||
setWillNotDraw(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Paint buildFillPaint(int color, Resources res) {
|
|
||||||
final Paint paint = new Paint();
|
|
||||||
|
|
||||||
paint.setColor(color);
|
|
||||||
paint.setStyle(Style.FILL_AND_STROKE);
|
|
||||||
paint.setAntiAlias(true);
|
|
||||||
|
|
||||||
if (FILL_GRADIENT) {
|
|
||||||
final int width = (int) (280 * res.getDisplayMetrics().density);
|
|
||||||
paint.setShader(new RadialGradient(0, 0, width, color, darken(color), TileMode.MIRROR));
|
|
||||||
}
|
|
||||||
|
|
||||||
return paint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOriginAngle(int originAngle) {
|
|
||||||
mOriginAngle = originAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addSlice(long value, int color) {
|
|
||||||
mSlices.add(new Slice(value, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeAllSlices() {
|
|
||||||
mSlices.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
|
||||||
final float centerX = getWidth() / 2;
|
|
||||||
final float centerY = getHeight() / 2;
|
|
||||||
|
|
||||||
mMatrix.reset();
|
|
||||||
mMatrix.postScale(0.665f, 0.95f, centerX, centerY);
|
|
||||||
mMatrix.postRotate(-40, centerX, centerY);
|
|
||||||
|
|
||||||
generatePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generatePath() {
|
|
||||||
if (LOGD) Log.d(TAG, "generatePath()");
|
|
||||||
|
|
||||||
long total = 0;
|
|
||||||
for (Slice slice : mSlices) {
|
|
||||||
slice.path.reset();
|
|
||||||
slice.pathSide.reset();
|
|
||||||
slice.pathOutline.reset();
|
|
||||||
total += slice.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPathSide.reset();
|
|
||||||
mPathSideOutline.reset();
|
|
||||||
mPathOutline.reset();
|
|
||||||
|
|
||||||
// bail when not enough stats to render
|
|
||||||
if (total == 0) {
|
|
||||||
invalidate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int width = getWidth();
|
|
||||||
final int height = getHeight();
|
|
||||||
|
|
||||||
final RectF rect = new RectF(0, 0, width, height);
|
|
||||||
final RectF rectSide = new RectF();
|
|
||||||
rectSide.set(rect);
|
|
||||||
rectSide.offset(-mSideWidth, 0);
|
|
||||||
|
|
||||||
mPathSide.addOval(rectSide, Direction.CW);
|
|
||||||
mPathSideOutline.addOval(rectSide, Direction.CW);
|
|
||||||
mPathOutline.addOval(rect, Direction.CW);
|
|
||||||
|
|
||||||
int startAngle = mOriginAngle;
|
|
||||||
for (Slice slice : mSlices) {
|
|
||||||
final int sweepAngle = (int) (slice.value * 360 / total);
|
|
||||||
final int endAngle = startAngle + sweepAngle;
|
|
||||||
|
|
||||||
final float startAngleMod = startAngle % 360;
|
|
||||||
final float endAngleMod = endAngle % 360;
|
|
||||||
final boolean startSideVisible = startAngleMod > 90 && startAngleMod < 270;
|
|
||||||
final boolean endSideVisible = endAngleMod > 90 && endAngleMod < 270;
|
|
||||||
|
|
||||||
// draw slice
|
|
||||||
slice.path.moveTo(rect.centerX(), rect.centerY());
|
|
||||||
slice.path.arcTo(rect, startAngle, sweepAngle);
|
|
||||||
slice.path.lineTo(rect.centerX(), rect.centerY());
|
|
||||||
|
|
||||||
if (startSideVisible || endSideVisible) {
|
|
||||||
|
|
||||||
// when start is beyond horizon, push until visible
|
|
||||||
final float startAngleSide = startSideVisible ? startAngle : 450;
|
|
||||||
final float endAngleSide = endSideVisible ? endAngle : 270;
|
|
||||||
final float sweepAngleSide = endAngleSide - startAngleSide;
|
|
||||||
|
|
||||||
// draw slice side
|
|
||||||
slice.pathSide.moveTo(rect.centerX(), rect.centerY());
|
|
||||||
slice.pathSide.arcTo(rect, startAngleSide, 0);
|
|
||||||
slice.pathSide.rLineTo(-mSideWidth, 0);
|
|
||||||
slice.pathSide.arcTo(rectSide, startAngleSide, sweepAngleSide);
|
|
||||||
slice.pathSide.rLineTo(mSideWidth, 0);
|
|
||||||
slice.pathSide.arcTo(rect, endAngleSide, -sweepAngleSide);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw slice outline
|
|
||||||
slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
|
|
||||||
slice.pathOutline.arcTo(rect, startAngle, 0);
|
|
||||||
if (startSideVisible) {
|
|
||||||
slice.pathOutline.rLineTo(-mSideWidth, 0);
|
|
||||||
}
|
|
||||||
slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
|
|
||||||
slice.pathOutline.arcTo(rect, startAngle + sweepAngle, 0);
|
|
||||||
if (endSideVisible) {
|
|
||||||
slice.pathOutline.rLineTo(-mSideWidth, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
startAngle += sweepAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDraw(Canvas canvas) {
|
|
||||||
|
|
||||||
canvas.concat(mMatrix);
|
|
||||||
|
|
||||||
for (Slice slice : mSlices) {
|
|
||||||
canvas.drawPath(slice.pathSide, slice.paint);
|
|
||||||
}
|
|
||||||
canvas.drawPath(mPathSideOutline, mPaintOutline);
|
|
||||||
|
|
||||||
for (Slice slice : mSlices) {
|
|
||||||
canvas.drawPath(slice.path, slice.paint);
|
|
||||||
canvas.drawPath(slice.pathOutline, mPaintOutline);
|
|
||||||
}
|
|
||||||
canvas.drawPath(mPathOutline, mPaintOutline);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int darken(int color) {
|
|
||||||
float[] hsv = new float[3];
|
|
||||||
Color.colorToHSV(color, hsv);
|
|
||||||
hsv[2] /= 2;
|
|
||||||
hsv[1] /= 2;
|
|
||||||
return Color.HSVToColor(hsv);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|