[2/2] OmniGears: Upgrade network traffic meter

*Implements list preferences where applicable to simplify the settings
*Add the ability to track Upstream, Downstream, or both
*Add the option to change the frequency with which it updates

PS3: add a config to disable network traffic meter
PS6: Update strings and check if stats are supported automatically

Base: https://gerrit.omnirom.org/#/c/5129/

PS8
use TrafficStats.UNSUPPORTED constant
use value as summary for list preference

PS10
use this to cleanup some of the other settings nor now

Change-Id: I778d981fb7a57d07127608f99d45936a55ae4898
diff --git a/res/values/custom_arrays.xml b/res/values/custom_arrays.xml
index 2f41fbe..1168011 100644
--- a/res/values/custom_arrays.xml
+++ b/res/values/custom_arrays.xml
@@ -382,4 +382,46 @@
         <item>EEEE dd/MM</item>
         <item>EEEE MM/dd</item>
     </string-array>
+
+    <!-- Network Traffic Display States -->
+    <string-array name="show_network_traffic_state_entries" translatable="false">
+        <item>@string/show_network_traffic_disable</item>
+        <item>@string/show_network_traffic_up</item>
+        <item>@string/show_network_traffic_down</item>
+        <item>@string/show_network_traffic_all</item>
+    </string-array>
+
+    <string-array name="show_network_traffic_state_values" translatable="false">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+    </string-array>
+
+    <!-- Network Traffic Display Unit -->
+    <string-array name="show_network_traffic_unit_entries" translatable="false">
+        <item>@string/show_network_traffic_bit</item>
+        <item>@string/show_network_traffic_byte</item>
+    </string-array>
+
+    <string-array name="show_network_traffic_unit_values" translatable="false">
+        <item>0</item>
+        <item>1</item>
+    </string-array>
+
+    <!-- Network Traffic Period -->
+    <string-array name="show_network_traffic_frequency_entries" translatable="false">
+        <item>@string/show_network_traffic_500</item>
+        <item>@string/show_network_traffic_1000</item>
+        <item>@string/show_network_traffic_1500</item>
+        <item>@string/show_network_traffic_2000</item>
+    </string-array>
+
+    <string-array name="show_network_traffic_frequency_values" translatable="false">
+        <item>500</item>
+        <item>1000</item>
+        <item>1500</item>
+        <item>2000</item>
+    </string-array>
+
 </resources>
diff --git a/res/values/custom_integers.xml b/res/values/custom_integers.xml
new file mode 100644
index 0000000..0b75685
--- /dev/null
+++ b/res/values/custom_integers.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2013 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<resources>
+
+    <!-- Overlays for NetworkTraffic to use -->
+    <integer name="maskUp">0x00000001</integer>
+    <integer name="maskDown">0x00000002</integer>
+    <integer name="maskUnit">0x00000004</integer>
+    <integer name="maskPeriod">0xFFFF0000</integer>
+</resources>
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
index 6b72fbb..b380a7d 100644
--- a/res/values/custom_strings.xml
+++ b/res/values/custom_strings.xml
@@ -159,15 +159,25 @@
     <string name="button_headsethook_launch_voice_title">Headset launches voice</string>
     <string name="button_headsethook_launch_voice_summary">Pressing the headset button will launch voice controls</string>
 
-    <!-- Network speed -->
-    <string name="show_network_speed">Network speed indicator</string>
-    <string name="show_network_speed_summary">Show network speed in statusbar</string>
-    <string name="show_network_speed_bits">Show speed as bits per second</string>
-    <string name="show_network_speed_bytes">Show speed as Bytes per second</string>
+    <!-- Network traffic -->
+    <string name="network_traffic_title">Network traffic</string>
+    <string name="show_network_traffic_state">Status bar traffic monitor</string>
+    <string name="show_network_traffic_unit">Display unit</string>
+    <string name="show_network_traffic_frequency">Update interval</string>
+    <string name="show_network_traffic_disable">Disabled</string>
+    <string name="show_network_traffic_up">Outgoing</string>
+    <string name="show_network_traffic_down">Incoming</string>
+    <string name="show_network_traffic_all">Outgoing and incoming</string>
+    <string name="show_network_traffic_bit">Bits per second</string>
+    <string name="show_network_traffic_byte">Bytes per second</string>
+    <string name="show_network_traffic_500">500 ms</string>
+    <string name="show_network_traffic_1000">1000 ms</string>
+    <string name="show_network_traffic_1500">1500 ms</string>
+    <string name="show_network_traffic_2000">2000 ms</string>
 
     <!-- Status Bar Activity Indicators -->
-    <string name="show_activity_indicators_on_status_bar_title">Network activity indicator</string>
-    <string name="show_activity_indicators_on_status_bar_summary">Show network activity in statusbar</string>
+    <string name="show_activity_indicators_on_status_bar_title">Activity indicators</string>
+    <string name="show_activity_indicators_on_status_bar_summary">Show indicators in signal bars</string>
 
     <!-- Hardware keys -->
     <string name="button_keys_title">Keys</string>
@@ -379,24 +389,26 @@
     <string name="icon_picker_sms">Messaging</string>
     <string name="icon_picker_twitter">Twitter</string>
 
+    <string name="quick_settings_category_title">Quick settings</string>
+
     <!-- QuickSettings: Dynamic Row -->
-    <string name="qs_configurable_title">QuickSettings configurable</string>
+    <string name="qs_configurable_title">Quick settings configurable</string>
     <string name="qs_configurable_summary">Enable/disable dynamic row changes</string>
 
     <!-- QuickSettings: Quick Pulldown -->
     <string name="title_quick_pulldown">Quick pulldown</string>
-    <string name="summary_quick_pulldown">Quickly pulldown quicksettings with one finger</string>
-    <string name="quick_pulldown_off">Off</string>
+    <string name="summary_quick_pulldown">Quickly pulldown quick settings with one finger</string>
+    <string name="quick_pulldown_off">Disabled</string>
     <string name="quick_pulldown_centre">Centre</string>
     <string name="quick_pulldown_left">Left</string>
     <string name="quick_pulldown_right">Right</string>
 
     <!-- QuickSettings: Smart Pulldown -->
     <string name="smart_pulldown_title">Smart pulldown</string>
-    <string name="smart_pulldown_summary">Open Quick Settings when there are no notifications present</string>
-    <string name="smart_pulldown_off">Off</string>
-    <string name="smart_pulldown_dismissable">Pulldown if there are no cleareable notifications</string>
-    <string name="smart_pulldown_persistent">Pulldown if there are no notifications</string>
+    <string name="smart_pulldown_summary">Open quick settings when there are no notifications present</string>
+    <string name="smart_pulldown_off">Disabled</string>
+    <string name="smart_pulldown_dismissable">If no cleareable notifications</string>
+    <string name="smart_pulldown_persistent">If no notifications</string>
 
     <!-- Cursor control -->
     <string name="volume_key_cursor_control_title">Cursor control</string>
diff --git a/res/xml/bars_settings.xml b/res/xml/bars_settings.xml
index 9b1d78c..f99a5f2 100644
--- a/res/xml/bars_settings.xml
+++ b/res/xml/bars_settings.xml
@@ -37,17 +37,16 @@
                 android:summary="@string/status_bar_notif_count_summary"
                 android:persistent="false"/>
 
-        <CheckBoxPreference
-                android:key="status_bar_traffic"
-                android:title="@string/show_network_speed"
-                android:summary="@string/show_network_speed_summary"
-                android:persistent="false" />
+        <PreferenceScreen
+                android:fragment="org.omnirom.omnigears.slim.StatusBarClockStyle"
+                android:key="clock_style_pref"
+                android:title="@string/status_bar_clock" />
 
-        <CheckBoxPreference
-                android:key="status_bar_network_activity"
-                android:title="@string/show_activity_indicators_on_status_bar_title"
-                android:summary="@string/show_activity_indicators_on_status_bar_summary"
-                android:persistent="false"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory
+            android:key="category_quick_settings"
+            android:title="@string/quick_settings_category_title">
 
         <ListPreference
                 android:key="quick_pulldown"
@@ -71,10 +70,39 @@
                 android:summary="@string/qs_configurable_summary"
                 android:persistent="false"/>
 
-        <PreferenceScreen
-                android:fragment="org.omnirom.omnigears.slim.StatusBarClockStyle"
-                android:key="clock_style_pref"
-                android:title="@string/status_bar_clock" />
+    </PreferenceCategory>
+
+    <!-- Network traffic meter -->
+    <PreferenceCategory
+            android:key="category_network_traffic"
+            android:title="@string/network_traffic_title">
+
+        <CheckBoxPreference
+                android:key="status_bar_network_activity"
+                android:title="@string/show_activity_indicators_on_status_bar_title"
+                android:summary="@string/show_activity_indicators_on_status_bar_summary"
+                android:persistent="false"/>
+
+        <ListPreference
+                android:key="network_traffic_state"
+                android:title="@string/show_network_traffic_state"
+                android:entries="@array/show_network_traffic_state_entries"
+                android:entryValues="@array/show_network_traffic_state_values"
+                android:persistent="false" />
+
+        <ListPreference
+                android:key="network_traffic_unit"
+                android:title="@string/show_network_traffic_unit"
+                android:entries="@array/show_network_traffic_unit_entries"
+                android:entryValues="@array/show_network_traffic_unit_values"
+                android:persistent="false" />
+
+        <ListPreference
+                android:key="network_traffic_period"
+                android:title="@string/show_network_traffic_frequency"
+                android:entries="@array/show_network_traffic_frequency_entries"
+                android:entryValues="@array/show_network_traffic_frequency_values"
+                android:persistent="false" />
 
     </PreferenceCategory>
 
diff --git a/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java b/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
index 023a1a4..9c822d1 100644
--- a/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
@@ -23,10 +23,13 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.Resources;
+import android.net.TrafficStats;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
 import android.preference.ListPreference;
 import android.preference.Preference;
 import android.preference.PreferenceGroup;
@@ -45,12 +48,14 @@
 
     private static final String STATUS_BAR_BRIGHTNESS_CONTROL = "status_bar_brightness_control";
     private static final String STATUS_BAR_NOTIF_COUNT = "status_bar_notif_count";
-    private static final String STATUS_BAR_TRAFFIC = "status_bar_traffic";
-    private static final String STATUS_BAR_NETWORK_ACTIVITY = "status_bar_network_activity";
     private static final String QUICK_PULLDOWN = "quick_pulldown";
     private static final String SMART_PULLDOWN = "smart_pulldown";
     private static final String QUICKSETTINGS_DYNAMIC = "quicksettings_dynamic_row";
     private static final String CATEGORY_NAVBAR = "category_navigation_bar";
+    private static final String NETWORK_TRAFFIC_STATE = "network_traffic_state";
+    private static final String NETWORK_TRAFFIC_UNIT = "network_traffic_unit";
+    private static final String NETWORK_TRAFFIC_PERIOD = "network_traffic_period";
+    private static final String STATUS_BAR_NETWORK_ACTIVITY = "status_bar_network_activity";
     private static final String SOFT_BACK_KILL_APP = "soft_back_kill_app";
     private static final String EMULATE_MENU_KEY = "emulate_menu_key";
 
@@ -61,19 +66,29 @@
 
     private CheckBoxPreference mStatusBarBrightnessControl;
     private CheckBoxPreference mStatusBarNotifCount;
-    private CheckBoxPreference mStatusBarTraffic;
-    private CheckBoxPreference mStatusBarNetworkActivity;
     private CheckBoxPreference mQuickSettingsDynamic;
     private ListPreference mQuickPulldown;
     private ListPreference mSmartPulldown;
+    private ListPreference mNetTrafficState;
+    private ListPreference mNetTrafficUnit;
+    private ListPreference mNetTrafficPeriod;
+    private CheckBoxPreference mStatusBarNetworkActivity;
     private CheckBoxPreference mSoftBackKillApp;
     private CheckBoxPreference mEmulateMenuKey;
 
+    private int mNetTrafficVal;
+    private int MASK_UP;
+    private int MASK_DOWN;
+    private int MASK_UNIT;
+    private int MASK_PERIOD;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         addPreferencesFromResource(R.xml.bars_settings);
 
+        loadResources();
+
         PreferenceScreen prefSet = getPreferenceScreen();
         ContentResolver resolver = getActivity().getContentResolver();
 
@@ -97,18 +112,6 @@
                 Settings.System.STATUS_BAR_NOTIF_COUNT, 0) == 1);
         mStatusBarNotifCount.setOnPreferenceChangeListener(this);
 
-        mStatusBarTraffic = (CheckBoxPreference) prefSet.findPreference(STATUS_BAR_TRAFFIC);
-        int intState = Settings.System.getInt(resolver, Settings.System.STATUS_BAR_TRAFFIC, 0);
-        intState = setStatusBarTrafficSummary(intState);
-        mStatusBarTraffic.setChecked(intState > 0);
-        mStatusBarTraffic.setOnPreferenceChangeListener(this);
-
-        mStatusBarNetworkActivity =
-                (CheckBoxPreference) prefSet.findPreference(STATUS_BAR_NETWORK_ACTIVITY);
-        mStatusBarNetworkActivity.setChecked(Settings.System.getInt(resolver,
-                Settings.System.STATUS_BAR_NETWORK_ACTIVITY, 0) == 1);
-        mStatusBarNetworkActivity.setOnPreferenceChangeListener(this);
-
         mQuickPulldown = (ListPreference) findPreference(QUICK_PULLDOWN);
         mSmartPulldown = (ListPreference) findPreference(SMART_PULLDOWN);
 
@@ -134,6 +137,45 @@
             Settings.System.QUICK_SETTINGS_TILES_ROW, 1) != 0);
         mQuickSettingsDynamic.setOnPreferenceChangeListener(this);
 
+        mStatusBarNetworkActivity =
+                (CheckBoxPreference) prefSet.findPreference(STATUS_BAR_NETWORK_ACTIVITY);
+        mStatusBarNetworkActivity.setChecked(Settings.System.getInt(resolver,
+                Settings.System.STATUS_BAR_NETWORK_ACTIVITY, 0) == 1);
+        mStatusBarNetworkActivity.setOnPreferenceChangeListener(this);
+
+        mNetTrafficState = (ListPreference) prefSet.findPreference(NETWORK_TRAFFIC_STATE);
+        mNetTrafficUnit = (ListPreference) prefSet.findPreference(NETWORK_TRAFFIC_UNIT);
+        mNetTrafficPeriod = (ListPreference) prefSet.findPreference(NETWORK_TRAFFIC_PERIOD);
+
+        // TrafficStats will return UNSUPPORTED if the device does not support it.
+        if (TrafficStats.getTotalTxBytes() != TrafficStats.UNSUPPORTED &&
+                TrafficStats.getTotalRxBytes() != TrafficStats.UNSUPPORTED) {
+            mNetTrafficVal = Settings.System.getInt(resolver, Settings.System.NETWORK_TRAFFIC_STATE, 0);
+            int intIndex = mNetTrafficVal & (MASK_UP + MASK_DOWN);
+            intIndex = mNetTrafficState.findIndexOfValue(String.valueOf(intIndex));
+            if (intIndex <= 0) {
+                mNetTrafficUnit.setEnabled(false);
+                mNetTrafficPeriod.setEnabled(false);
+            }
+            mNetTrafficState.setValueIndex(intIndex >= 0 ? intIndex : 0);
+            mNetTrafficState.setSummary(mNetTrafficState.getEntry());
+            mNetTrafficState.setOnPreferenceChangeListener(this);
+
+            mNetTrafficUnit.setValueIndex(getBit(mNetTrafficVal, MASK_UNIT) ? 1 : 0);
+            mNetTrafficUnit.setSummary(mNetTrafficUnit.getEntry());
+            mNetTrafficUnit.setOnPreferenceChangeListener(this);
+
+            intIndex = (mNetTrafficVal & MASK_PERIOD) >>> 16;
+            intIndex = mNetTrafficPeriod.findIndexOfValue(String.valueOf(intIndex));
+            mNetTrafficPeriod.setValueIndex(intIndex >= 0 ? intIndex : 1);
+            mNetTrafficPeriod.setSummary(mNetTrafficPeriod.getEntry());
+            mNetTrafficPeriod.setOnPreferenceChangeListener(this);
+        } else {
+            prefSet.removePreference(findPreference(NETWORK_TRAFFIC_STATE));
+            prefSet.removePreference(findPreference(NETWORK_TRAFFIC_UNIT));
+            prefSet.removePreference(findPreference(NETWORK_TRAFFIC_PERIOD));
+        }
+
         boolean hasNavBar = getResources().getBoolean(
                 com.android.internal.R.bool.config_showNavigationBar);
         // Also check, if users without navigation bar force enabled it.
@@ -171,32 +213,48 @@
         } else if (preference == mStatusBarNotifCount) {
             boolean value = (Boolean) objValue;
             Settings.System.putInt(resolver, Settings.System.STATUS_BAR_NOTIF_COUNT, value ? 1 : 0);
-        } else if (preference == mStatusBarTraffic) {
-
-            // Increment the state and then update the label
-            int intState = Settings.System.getInt(resolver, Settings.System.STATUS_BAR_TRAFFIC, 0);
-            intState++;
-            intState = setStatusBarTrafficSummary(intState);
-            Settings.System.putInt(resolver, Settings.System.STATUS_BAR_TRAFFIC, intState);
-            if (intState > 1) {return false;}
-        } else if (preference == mStatusBarNetworkActivity) {
-            boolean value = (Boolean) objValue;
-            Settings.System.putInt(resolver, Settings.System.STATUS_BAR_NETWORK_ACTIVITY,
-                    value ? 1 : 0);
         } else if (preference == mQuickSettingsDynamic) {
             boolean value = (Boolean) objValue;
             Settings.System.putInt(resolver,
                 Settings.System.QUICK_SETTINGS_TILES_ROW, value ? 1 : 0);
         } else if (preference == mQuickPulldown) {
             int quickPulldown = Integer.valueOf((String) objValue);
-            Settings.System.putInt(resolver, Settings.System.QS_QUICK_PULLDOWN,
-                    quickPulldown);
+            Settings.System.putInt(resolver, Settings.System.QS_QUICK_PULLDOWN, quickPulldown);
             updateQuickPulldownSummary(quickPulldown);
         } else if (preference == mSmartPulldown) {
             int smartPulldown = Integer.valueOf((String) objValue);
-            Settings.System.putInt(resolver, Settings.System.QS_SMART_PULLDOWN,
-                    smartPulldown);
+            Settings.System.putInt(resolver, Settings.System.QS_SMART_PULLDOWN, smartPulldown);
             updateSmartPulldownSummary(smartPulldown);
+        } else if (preference == mStatusBarNetworkActivity) {
+            boolean value = (Boolean) objValue;
+            Settings.System.putInt(resolver, Settings.System.STATUS_BAR_NETWORK_ACTIVITY,
+                    value ? 1 : 0);
+        } else if (preference == mNetTrafficState) {
+            int intState = Integer.valueOf((String)objValue);
+            mNetTrafficVal = setBit(mNetTrafficVal, MASK_UP, getBit(intState, MASK_UP));
+            mNetTrafficVal = setBit(mNetTrafficVal, MASK_DOWN, getBit(intState, MASK_DOWN));
+            Settings.System.putInt(resolver, Settings.System.NETWORK_TRAFFIC_STATE, mNetTrafficVal);
+            int index = mNetTrafficState.findIndexOfValue((String) objValue);
+            mNetTrafficState.setSummary(mNetTrafficState.getEntries()[index]);
+            if (intState == 0) {
+                mNetTrafficUnit.setEnabled(false);
+                mNetTrafficPeriod.setEnabled(false);
+            } else {
+                mNetTrafficUnit.setEnabled(true);
+                mNetTrafficPeriod.setEnabled(true);
+            }
+        } else if (preference == mNetTrafficUnit) {
+            // 1 = Display as Byte/s; default is bit/s
+            mNetTrafficVal = setBit(mNetTrafficVal, MASK_UNIT, ((String)objValue).equals("1"));
+            Settings.System.putInt(resolver, Settings.System.NETWORK_TRAFFIC_STATE, mNetTrafficVal);
+            int index = mNetTrafficUnit.findIndexOfValue((String) objValue);
+            mNetTrafficUnit.setSummary(mNetTrafficUnit.getEntries()[index]);
+        } else if (preference == mNetTrafficPeriod) {
+            int intState = Integer.valueOf((String)objValue);
+            mNetTrafficVal = setBit(mNetTrafficVal, MASK_PERIOD, false) + (intState << 16);
+            Settings.System.putInt(resolver, Settings.System.NETWORK_TRAFFIC_STATE, mNetTrafficVal);
+            int index = mNetTrafficPeriod.findIndexOfValue((String) objValue);
+            mNetTrafficPeriod.setSummary(mNetTrafficPeriod.getEntries()[index]);
         } else if (preference == mSoftBackKillApp) {
             boolean value = (Boolean) objValue;
             Settings.System.putInt(resolver,
@@ -211,17 +269,24 @@
         return true;
     }
 
-    private int setStatusBarTrafficSummary(int intState) {
-        // These states must match com.android.systemui.statusbar.policy.Traffic
-        if (intState == 1) {
-            mStatusBarTraffic.setSummary(R.string.show_network_speed_bits);
-        } else if (intState == 2) {
-            mStatusBarTraffic.setSummary(R.string.show_network_speed_bytes);
-        } else {
-            mStatusBarTraffic.setSummary(R.string.show_network_speed_summary);
-            return 0;
+    private void loadResources() {
+        Resources resources = getActivity().getResources();
+        MASK_UP = resources.getInteger(R.integer.maskUp);
+        MASK_DOWN = resources.getInteger(R.integer.maskDown);
+        MASK_UNIT = resources.getInteger(R.integer.maskUnit);
+        MASK_PERIOD = resources.getInteger(R.integer.maskPeriod);
+    }
+
+    // intMask should only have the desired bit(s) set
+    private int setBit(int intNumber, int intMask, boolean blnState) {
+        if (blnState) {
+            return (intNumber | intMask);
         }
-        return intState;
+        return (intNumber & ~intMask);
+    }
+
+    private boolean getBit(int intNumber, int intMask) {
+        return (intNumber & intMask) == intMask;
     }
 
     private void updateQuickPulldownSummary(int i) {