Attempt to make data saver mode work for real.

The data saver refactoring change was incorrect in >= two ways:

1. It relied on the bw_costly_shared chain, which is currently
   unused. NetworkManagementService just has a "TODO: support
   quota shared across interfaces" comment about it. What
   actually happens when setting quota is that each costly
   interface chain (e.g., bw_costly_rmnet_data0) directly hooks
   in the bw_penalty box chain.

2. Implementing app whitelisting using "RETURN" inside
   bw_happy_box was pointless because if data saver was enabled,
   there was a REJECT at the end of the bw_costly_shared chain
   that it was returning to.

Instead, go back to the previous approach which hooked
bw_happy_box at the end of bw_penalty_box. Also, add an
additional bw_data_saver rule at the end of bw_happy_box.
bw_data_saver only contains one rule: RETURN if data saver is
enabled or REJECT if data saver is disabled.

That way:

1. If the app is blacklisted, bw_penalty_box REJECTs. If not:
2. If the app is whitelisted (system apps are always whitelisted)
   bw_happy_box RETURNs to bw_costly_rmnet_data0, skipping
   bw_data_saver.
3. If an app is neither blacklisted nor whitelisted, bw_happy_box
   jumps to bw_data_saver. If data saver is enabled, it REJECTs
   the packet, and if not, it RETURNs to bw_costly_rmnet_data0.
4. When we RETURN to bw_costly_rmnet_data0, either because the
   app is whitelisted, or because data saver is off,
   bw_costly_rmnet_data0 applies mobile data usage limits,
   and then RETURNs to bw_OUTPUT, which calls xt_qtaguid, etc.

Bug: 26685616
Bug: 27506285
Change-Id: If15397afde6862d95827a1fdd30f60efd7fab66a
diff --git a/server/BandwidthController.cpp b/server/BandwidthController.cpp
index 2f129ab..51bb29f 100644
--- a/server/BandwidthController.cpp
+++ b/server/BandwidthController.cpp
@@ -77,7 +77,6 @@
  *    - when an interface is marked as costly it should be INSERTED into the INPUT/OUTPUT chains.
  *      E.g. "-I bw_INPUT -i rmnet0 --jump costly"
  *    - quota'd rules in the costly chain should be before bw_penalty_box lookups.
- *    - bw_happy_box rejects everything by default.
  *    - the qtaguid counting is done at the end of the bw_INPUT/bw_OUTPUT user chains.
  *
  * * global quota vs per interface quota
@@ -90,6 +89,7 @@
  *          --jump REJECT --reject-with icmp-net-prohibited
  *      iptables -A bw_costly_shared --jump bw_penalty_box
  *      iptables -A bw_penalty_box --jump bw_happy_box
+ *      iptables -A bw_happy_box --jump bw_data_saver
  *
  *    . adding a new iface to this, E.g.:
  *      iptables -I bw_INPUT -i iface1 --jump bw_costly_shared
@@ -104,6 +104,15 @@
  *          --jump REJECT --reject-with icmp-port-unreachable
  *      iptables -A bw_costly_iface0 --jump bw_penalty_box
  *
+ * * Penalty box, happy box and data saver.
+ *   - bw_penalty box is a blacklist of apps that are rejected.
+ *   - bw_happy_box is a whitelist of apps. It always includes all system apps
+ *   - bw_data_saver implements data usage restrictions.
+ *   - Via the UI the user can add and remove apps from the whitelist and
+ *     blacklist, and turn on/off data saver.
+ *   - The blacklist takes precedence over the whitelist and the whitelist
+ *     takes precedence over data saver.
+ *
  * * bw_penalty_box handling:
  *  - only one bw_penalty_box for all interfaces
  *   E.g  Adding an app:
@@ -116,10 +125,12 @@
  *    iptables -I bw_happy_box -m owner --uid-owner app_3 \
  *        --jump RETURN
  *
- * * Turning data saver on and off:
- *  - Adds or removes a REJECT at the end of the bw_costly_shared chain
- *    iptables -A bw_costly_shared --jump REJECT --reject-with icmp-port-unreachable
- *    iptables -D bw_costly_shared --jump REJECT --reject-with icmp-port-unreachable
+ * * bw_data_saver handling:
+ *  - The bw_data_saver comes after the happy box.
+ *    Enable data saver:
+ *      iptables -R 1 bw_data_saver --jump REJECT --reject-with icmp-port-unreachable
+ *    Disable data saver:
+ *      iptables -R 1 bw_data_saver --jump RETURN
  */
 
 const char *IPT_FLUSH_COMMANDS[] = {
@@ -133,6 +144,7 @@
     "-F bw_FORWARD",
     "-F bw_happy_box",
     "-F bw_penalty_box",
+    "-F bw_data_saver",
     "-F bw_costly_shared",
 
     "-t raw -F bw_raw_PREROUTING",
@@ -143,12 +155,14 @@
 const char *IPT_CLEANUP_COMMANDS[] = {
     "-X bw_happy_box",
     "-X bw_penalty_box",
+    "-X bw_data_saver",
     "-X bw_costly_shared",
 };
 
 const char *IPT_SETUP_COMMANDS[] = {
     "-N bw_happy_box",
     "-N bw_penalty_box",
+    "-N bw_data_saver",
     "-N bw_costly_shared",
 };
 
@@ -159,16 +173,15 @@
 
     "-t raw -A bw_raw_PREROUTING -m owner --socket-exists", /* This is a tracking rule. */
     "-t mangle -A bw_mangle_POSTROUTING -m owner --socket-exists", /* This is a tracking rule. */
-};
 
-const char *COSTLY_SHARED_COMMANDS[] = {
     "-A bw_costly_shared --jump bw_penalty_box",
-    "-A bw_costly_shared --jump bw_happy_box",
-    "-A bw_costly_shared --jump RETURN",
+
+    "-A bw_penalty_box --jump bw_happy_box",
+    "-A bw_happy_box --jump bw_data_saver",
+    "-A bw_data_saver -j RETURN",
 };
 
-const std::string kDataSaverEnableCommand = android::base::StringPrintf(
-        "-R bw_costly_shared %zu", ARRAY_SIZE(COSTLY_SHARED_COMMANDS));
+const std::string kDataSaverEnableCommand = "-R bw_data_saver 1";
 
 }  // namespace
 
@@ -293,12 +306,9 @@
     res = runCommands(ARRAY_SIZE(IPT_BASIC_ACCOUNTING_COMMANDS),
             IPT_BASIC_ACCOUNTING_COMMANDS, RunCmdFailureBad);
 
-    res |= runCommands(ARRAY_SIZE(COSTLY_SHARED_COMMANDS),
-            COSTLY_SHARED_COMMANDS, RunCmdFailureBad);
-
     char cmd[MAX_CMD_LEN];
     snprintf(cmd, sizeof(cmd),
-            "-A bw_happy_box -m owner --uid-owner %d-%d", 0, MAX_SYSTEM_UID);
+            "-I bw_happy_box -m owner --uid-owner %d-%d", 0, MAX_SYSTEM_UID);
     runIpxtablesCmd(cmd, IptJumpReturn);
 
     return res;