Merge "Enabled Network Policy Backup/Restore." into mm-wireless-dev
am: d9c4bc0c4d

* commit 'd9c4bc0c4db7a8b16d8ea0f58ed0615efc167f47':
  Enabled Network Policy Backup/Restore.
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index e88bc26..9870e7b 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -20,7 +20,12 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.BackupUtils;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
 import java.util.Objects;
 
 /**
@@ -30,6 +35,11 @@
  * @hide
  */
 public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
+    /**
+     * Current Version of the Backup Serializer.
+     */
+    private static final int BACKUP_VERSION = 1;
+
     public static final int CYCLE_NONE = -1;
     public static final long WARNING_DISABLED = -1;
     public static final long LIMIT_DISABLED = -1;
@@ -191,4 +201,41 @@
             return new NetworkPolicy[size];
         }
     };
+
+    public byte[] getBytesForBackup() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        DataOutputStream out = new DataOutputStream(baos);
+
+        out.writeInt(BACKUP_VERSION);
+        out.write(template.getBytesForBackup());
+        out.writeInt(cycleDay);
+        BackupUtils.writeString(out, cycleTimezone);
+        out.writeLong(warningBytes);
+        out.writeLong(limitBytes);
+        out.writeLong(lastWarningSnooze);
+        out.writeLong(lastLimitSnooze);
+        out.writeInt(metered ? 1 : 0);
+        out.writeInt(inferred ? 1 : 0);
+        return baos.toByteArray();
+    }
+
+    public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException,
+            BackupUtils.BadVersionException {
+        int version = in.readInt();
+        if (version < 1 || version > BACKUP_VERSION) {
+            throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+        }
+
+        NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
+        int cycleDay = in.readInt();
+        String cycleTimeZone = BackupUtils.readString(in);
+        long warningBytes = in.readLong();
+        long limitBytes = in.readLong();
+        long lastWarningSnooze = in.readLong();
+        long lastLimitSnooze = in.readLong();
+        boolean metered = in.readInt() == 1;
+        boolean inferred = in.readInt() == 1;
+        return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes, limitBytes,
+                lastWarningSnooze, lastLimitSnooze, metered, inferred);
+    }
 }
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b7a411e..5761d66 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -28,15 +28,21 @@
 import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
 import static android.telephony.TelephonyManager.getNetworkClass;
+
 import static com.android.internal.util.ArrayUtils.contains;
 
 import android.content.res.Resources;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.BackupUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Objects;
 
@@ -47,6 +53,10 @@
  * @hide
  */
 public class NetworkTemplate implements Parcelable {
+    /**
+     * Current Version of the Backup Serializer.
+     */
+    private static final int BACKUP_VERSION = 1;
 
     public static final int MATCH_MOBILE_ALL = 1;
     @Deprecated
@@ -443,4 +453,31 @@
             return new NetworkTemplate[size];
         }
     };
+
+    public byte[] getBytesForBackup() throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        DataOutputStream out = new DataOutputStream(baos);
+
+        out.writeInt(BACKUP_VERSION);
+
+        out.writeInt(mMatchRule);
+        BackupUtils.writeString(out, mSubscriberId);
+        BackupUtils.writeString(out, mNetworkId);
+
+        return baos.toByteArray();
+    }
+
+    public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
+            throws IOException, BackupUtils.BadVersionException {
+        int version = in.readInt();
+        if (version < 1 || version > BACKUP_VERSION) {
+            throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+        }
+
+        int matchRule = in.readInt();
+        String subscriberId = BackupUtils.readString(in);
+        String networkId = BackupUtils.readString(in);
+
+        return new NetworkTemplate(matchRule, subscriberId, networkId);
+    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index a8d7464..029a125 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -24,6 +24,8 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -83,23 +85,29 @@
     private static final String KEY_LOCALE = "locale";
     private static final String KEY_LOCK_SETTINGS = "lock_settings";
     private static final String KEY_SOFTAP_CONFIG = "softap_config";
+    private static final String KEY_NETWORK_POLICIES = "network_policies";
 
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
-    private static final int STATE_VERSION = 5;
+    private static final int STATE_VERSION = 6;
+
+    // Versioning of the Network Policies backup payload.
+    private static final int NETWORK_POLICIES_BACKUP_VERSION = 1;
+
 
     // Slots in the checksum array.  Never insert new items in the middle
     // of this array; new slots must be appended.
-    private static final int STATE_SYSTEM          = 0;
-    private static final int STATE_SECURE          = 1;
-    private static final int STATE_LOCALE          = 2;
-    private static final int STATE_WIFI_SUPPLICANT = 3;
-    private static final int STATE_WIFI_CONFIG     = 4;
-    private static final int STATE_GLOBAL          = 5;
-    private static final int STATE_LOCK_SETTINGS   = 6;
-    private static final int STATE_SOFTAP_CONFIG   = 7;
+    private static final int STATE_SYSTEM           = 0;
+    private static final int STATE_SECURE           = 1;
+    private static final int STATE_LOCALE           = 2;
+    private static final int STATE_WIFI_SUPPLICANT  = 3;
+    private static final int STATE_WIFI_CONFIG      = 4;
+    private static final int STATE_GLOBAL           = 5;
+    private static final int STATE_LOCK_SETTINGS    = 6;
+    private static final int STATE_SOFTAP_CONFIG    = 7;
+    private static final int STATE_NETWORK_POLICIES = 8;
 
-    private static final int STATE_SIZE            = 8; // The current number of state items
+    private static final int STATE_SIZE             = 9; // The current number of state items
 
     // Number of entries in the checksum array at various version numbers
     private static final int STATE_SIZES[] = {
@@ -108,15 +116,17 @@
             5,              // version 2 added STATE_WIFI_CONFIG
             6,              // version 3 added STATE_GLOBAL
             7,              // version 4 added STATE_LOCK_SETTINGS
-            STATE_SIZE      // version 5 added STATE_SOFTAP_CONFIG
+            8,              // version 5 added STATE_SOFTAP_CONFIG
+            STATE_SIZE      // version 6 added STATE_NETWORK_POLICIES
     };
 
     // Versioning of the 'full backup' format
     // Increment this version any time a new item is added
-    private static final int FULL_BACKUP_VERSION = 4;
+    private static final int FULL_BACKUP_VERSION = 5;
     private static final int FULL_BACKUP_ADDED_GLOBAL = 2;  // added the "global" entry
     private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
     private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry
+    private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies"
 
     private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
 
@@ -412,6 +422,7 @@
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
         byte[] softApConfigData = getSoftAPConfiguration();
+        byte[] netPoliciesData = getNetworkPolicies();
 
         long[] stateChecksums = readOldChecksums(oldState);
 
@@ -435,6 +446,9 @@
         stateChecksums[STATE_SOFTAP_CONFIG] =
                 writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
                         softApConfigData, data);
+        stateChecksums[STATE_NETWORK_POLICIES] =
+                writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES,
+                        netPoliciesData, data);
 
         writeNewChecksums(stateChecksums, newState);
     }
@@ -592,6 +606,12 @@
                     restoreSoftApConfiguration(softapData);
                     break;
 
+                case KEY_NETWORK_POLICIES:
+                    byte[] netPoliciesData = new byte[size];
+                    data.readEntityData(netPoliciesData, 0, size);
+                    restoreNetworkPolicies(netPoliciesData);
+                    break;
+
                 default :
                     data.skipEntityData();
 
@@ -622,6 +642,7 @@
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
         byte[] softApConfigData = getSoftAPConfiguration();
+        byte[] netPoliciesData = getNetworkPolicies();
 
         // Write the data to the staging file, then emit that as our tarfile
         // representation of the backed-up settings.
@@ -665,6 +686,9 @@
             if (DEBUG_BACKUP) Log.d(TAG, softApConfigData.length + " bytes of softap config data");
             out.writeInt(softApConfigData.length);
             out.write(softApConfigData);
+            if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of net policies data");
+            out.writeInt(netPoliciesData.length);
+            out.write(netPoliciesData);
 
             out.flush();    // also flushes downstream
 
@@ -766,7 +790,16 @@
                     restoreSoftApConfiguration(buffer);
                 }
             }
-
+            // network policies
+            if (version >= FULL_BACKUP_ADDED_NETWORK_POLICIES) {
+                nBytes = in.readInt();
+                if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of network policies data");
+                if (nBytes > buffer.length) buffer = new byte[nBytes];
+                if (nBytes > 0) {
+                    in.readFully(buffer, 0, nBytes);
+                    restoreNetworkPolicies(buffer);
+                }
+            }
             if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
         } else {
             data.close();
@@ -1114,7 +1147,6 @@
                 }
             }
         }
-
     }
 
     private void restoreFileData(String filename, byte[] bytes, int size) {
@@ -1239,6 +1271,65 @@
         }
     }
 
+    private byte[] getNetworkPolicies() {
+        NetworkPolicyManager networkPolicyManager =
+                (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
+        NetworkPolicy[] policies = networkPolicyManager.getNetworkPolicies();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        if (policies != null && policies.length != 0) {
+            DataOutputStream out = new DataOutputStream(baos);
+            try {
+                out.writeInt(NETWORK_POLICIES_BACKUP_VERSION);
+                out.writeInt(policies.length);
+                for (NetworkPolicy policy : policies) {
+                    if (policy != null) {
+                        byte[] marshaledPolicy = policy.getBytesForBackup();
+                        out.writeByte(BackupUtils.NOT_NULL);
+                        out.writeInt(marshaledPolicy.length);
+                        out.write(marshaledPolicy);
+                    } else {
+                        out.writeByte(BackupUtils.NULL);
+                    }
+                }
+            } catch (IOException ioe) {
+                Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage());
+                baos.reset();
+            }
+        }
+        return baos.toByteArray();
+    }
+
+    private void restoreNetworkPolicies(byte[] data) {
+        NetworkPolicyManager networkPolicyManager =
+                (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
+        if (data != null && data.length != 0) {
+            DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
+            try {
+                int version = in.readInt();
+                if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) {
+                    throw new BackupUtils.BadVersionException(
+                            "Unknown Backup Serialization Version");
+                }
+                int length = in.readInt();
+                NetworkPolicy[] policies = new NetworkPolicy[length];
+                for (int i = 0; i < length; i++) {
+                    byte isNull = in.readByte();
+                    if (isNull == BackupUtils.NULL) continue;
+                    int byteLength = in.readInt();
+                    byte[] policyData = new byte[byteLength];
+                    in.read(policyData, 0, byteLength);
+                    policies[i] = NetworkPolicy.getNetworkPolicyFromBackup(
+                            new DataInputStream(new ByteArrayInputStream(policyData)));
+                }
+                // Only set the policies if there was no error in the restore operation
+                networkPolicyManager.setNetworkPolicies(policies);
+            } catch (NullPointerException | IOException | BackupUtils.BadVersionException e) {
+                // NPE can be thrown when trying to instantiate a NetworkPolicy
+                Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage());
+            }
+        }
+    }
+
     /**
      * Write an int in BigEndian into the byte array.
      * @param out byte array