OSDN Git Service

Enabled NetworkPolicy backup and restore.
authorRitesh Reddy <riteshr@google.com>
Wed, 9 Dec 2015 14:01:18 +0000 (14:01 +0000)
committerRitesh Reddy <riteshr@google.com>
Thu, 10 Dec 2015 16:21:18 +0000 (16:21 +0000)
Backing up NetworkPolicy through NetworkPolicyManager API

Bug: 17857156
Change-Id: I2363e66a1b27f50b2454b4550a241a3d84bf4b7c

packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java [new file with mode: 0644]
packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
packages/SettingsProvider/test/Android.mk
packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java [new file with mode: 0644]

diff --git a/packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java b/packages/SettingsProvider/src/com/android/providers/settings/NetworkPolicySerializer.java
new file mode 100644 (file)
index 0000000..4b87da4
--- /dev/null
@@ -0,0 +1,186 @@
+package com.android.providers.settings;
+
+import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Backup/Restore Serializer Class for android.net.NetworkPolicy
+ */
+public class NetworkPolicySerializer {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "NetworkPolicySerializer";
+
+    private static final int NULL = 0;
+    private static final int NOT_NULL = 1;
+    /**
+     * Current Version of the Serializer.
+     */
+    private static int STATE_VERSION = 1;
+
+    /**
+     * Marshals an array of NetworkPolicy objects into a byte-array.
+     *
+     * @param policies - NetworkPolicies to be Marshaled
+     * @return byte array
+     */
+
+    public static byte[] marshalNetworkPolicies(NetworkPolicy policies[]) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        if (policies != null && policies.length != 0) {
+            DataOutputStream out = new DataOutputStream(baos);
+            try {
+                out.writeInt(STATE_VERSION);
+                out.writeInt(policies.length);
+                for (NetworkPolicy policy : policies) {
+                    byte[] marshaledPolicy = marshalNetworkPolicy(policy);
+                    if (marshaledPolicy != null) {
+                        out.writeByte(NOT_NULL);
+                        out.writeInt(marshaledPolicy.length);
+                        out.write(marshaledPolicy);
+                    } else {
+                        out.writeByte(NULL);
+                    }
+                }
+            } catch (IOException ioe) {
+                Log.e(TAG, "Failed to Convert NetworkPolicies to byte array", ioe);
+                baos.reset();
+            }
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * Unmarshals a byte array into an array of NetworkPolicy Objects
+     *
+     * @param data - marshaled NetworkPolicies Array
+     * @return NetworkPolicy[] array
+     */
+    public static NetworkPolicy[] unmarshalNetworkPolicies(byte[] data) {
+        if (data == null || data.length == 0) {
+            return new NetworkPolicy[0];
+        }
+        DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
+        try {
+            int version = in.readInt();
+            int length = in.readInt();
+            NetworkPolicy[] policies = new NetworkPolicy[length];
+            for (int i = 0; i < length; i++) {
+                byte isNull = in.readByte();
+                if (isNull == NULL) continue;
+                int byteLength = in.readInt();
+                byte[] policyData = new byte[byteLength];
+                in.read(policyData, 0, byteLength);
+                policies[i] = unmarshalNetworkPolicy(policyData);
+            }
+            return policies;
+        } catch (IOException ioe) {
+            Log.e(TAG, "Failed to Convert byte array to NetworkPolicies", ioe);
+            return new NetworkPolicy[0];
+        }
+    }
+
+    /**
+     * Marshals a NetworkPolicy object into a byte-array.
+     *
+     * @param networkPolicy - NetworkPolicy to be Marshaled
+     * @return byte array
+     */
+    public static byte[] marshalNetworkPolicy(NetworkPolicy networkPolicy) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        if (networkPolicy != null) {
+            DataOutputStream out = new DataOutputStream(baos);
+            try {
+                out.writeInt(STATE_VERSION);
+                writeNetworkTemplate(out, networkPolicy.template);
+                out.writeInt(networkPolicy.cycleDay);
+                writeString(out, networkPolicy.cycleTimezone);
+                out.writeLong(networkPolicy.warningBytes);
+                out.writeLong(networkPolicy.limitBytes);
+                out.writeLong(networkPolicy.lastWarningSnooze);
+                out.writeLong(networkPolicy.lastLimitSnooze);
+                out.writeInt(networkPolicy.metered ? 1 : 0);
+                out.writeInt(networkPolicy.inferred ? 1 : 0);
+            } catch (IOException ioe) {
+                Log.e(TAG, "Failed to Convert NetworkPolicy to byte array", ioe);
+                baos.reset();
+            }
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * Unmarshals a byte array into a NetworkPolicy Object
+     *
+     * @param data - marshaled NetworkPolicy Object
+     * @return NetworkPolicy Object
+     */
+    public static NetworkPolicy unmarshalNetworkPolicy(byte[] data) {
+        if (data == null || data.length == 0) {
+            return null;
+        }
+        DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
+        try {
+            int version = in.readInt();
+            NetworkTemplate template = readNetworkTemplate(in, version);
+            int cycleDay = in.readInt();
+            String cycleTimeZone = readString(in, version);
+            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);
+        } catch (IOException ioe) {
+            Log.e(TAG, "Failed to Convert byte array to NetworkPolicy", ioe);
+            return null;
+        }
+    }
+
+    private static NetworkTemplate readNetworkTemplate(DataInputStream in, int version)
+            throws IOException {
+        byte isNull = in.readByte();
+        if (isNull == NULL) return null;
+        int matchRule = in.readInt();
+        String subscriberId = readString(in, version);
+        String networkId = readString(in, version);
+        return new NetworkTemplate(matchRule, subscriberId, networkId);
+    }
+
+    private static void writeNetworkTemplate(DataOutputStream out, NetworkTemplate template)
+            throws IOException {
+        if (template != null) {
+            out.writeByte(NOT_NULL);
+            out.writeInt(template.getMatchRule());
+            writeString(out, template.getSubscriberId());
+            writeString(out, template.getNetworkId());
+        } else {
+            out.writeByte(NULL);
+        }
+    }
+
+    private static String readString(DataInputStream in, int version) throws IOException {
+        byte isNull = in.readByte();
+        if (isNull == NOT_NULL) {
+            return in.readUTF();
+        }
+        return null;
+    }
+
+    private static void writeString(DataOutputStream out, String val) throws IOException {
+        if (val != null) {
+            out.writeByte(NOT_NULL);
+            out.writeUTF(val);
+        } else {
+            out.writeByte(NULL);
+        }
+    }
+}
index 8910af4..185a03f 100644 (file)
@@ -24,6 +24,7 @@ import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.net.NetworkPolicyManager;
 import android.net.Uri;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -82,10 +83,12 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     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_NET_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;
 
     // Slots in the checksum array.  Never insert new items in the middle
     // of this array; new slots must be appended.
@@ -97,8 +100,9 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     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_NET_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[] = {
@@ -107,7 +111,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
             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_NET_POLICIES
     };
 
     // Versioning of the 'full backup' format
@@ -115,6 +120,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     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_NET_POLICIES = 5; //added the "network_policies" entry
 
     private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
 
@@ -410,6 +416,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
         byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
         byte[] wifiConfigData = getFileData(mWifiConfigFile);
         byte[] softApConfigData = getSoftAPConfiguration();
+        byte[] netPoliciesData = getNetworkPolicies();
 
         long[] stateChecksums = readOldChecksums(oldState);
 
@@ -433,6 +440,9 @@ public class SettingsBackupAgent extends BackupAgentHelper {
         stateChecksums[STATE_SOFTAP_CONFIG] =
                 writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
                         softApConfigData, data);
+        stateChecksums[STATE_NET_POLICIES] =
+                writeIfChanged(stateChecksums[STATE_NET_POLICIES], KEY_NET_POLICIES,
+                        netPoliciesData, data);
 
         writeNewChecksums(stateChecksums, newState);
     }
@@ -573,6 +583,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                 byte[] softapData = new byte[size];
                 data.readEntityData(softapData, 0, size);
                 restoreSoftApConfiguration(softapData);
+            } else if (KEY_NET_POLICIES.equals(key)) {
+                byte[] netPoliciesData = new byte[size];
+                data.readEntityData(netPoliciesData, 0, size);
+                restoreNetworkPolicies(netPoliciesData);
             } else {
                 data.skipEntityData();
             }
@@ -602,6 +616,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
         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.
@@ -639,6 +654,9 @@ public class SettingsBackupAgent extends BackupAgentHelper {
             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 network policies data");
+            out.writeInt(netPoliciesData.length);
+            out.write(netPoliciesData);
 
             out.flush();    // also flushes downstream
 
@@ -741,6 +759,16 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                 }
             }
 
+            if (version >= FULL_BACKUP_ADDED_NET_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();
@@ -1196,6 +1224,20 @@ public class SettingsBackupAgent extends BackupAgentHelper {
         wifiManager.setWifiApConfiguration(WiFiConfigurationSerializer.unmarshalWifiConfig(data));
     }
 
+    private byte[] getNetworkPolicies(){
+        NetworkPolicyManager networkPolicyManager =
+                (NetworkPolicyManager)getSystemService(NETWORK_POLICY_SERVICE);
+        return NetworkPolicySerializer
+                .marshalNetworkPolicies(networkPolicyManager.getNetworkPolicies());
+    }
+
+    private void restoreNetworkPolicies(byte[] data){
+        NetworkPolicyManager networkPolicyManager =
+                (NetworkPolicyManager)getSystemService(NETWORK_POLICY_SERVICE);
+        networkPolicyManager
+                .setNetworkPolicies(NetworkPolicySerializer.unmarshalNetworkPolicies(data));
+    }
+
     /**
      * Write an int in BigEndian into the byte array.
      * @param out byte array
@@ -1217,11 +1259,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     }
 
     private int readInt(byte[] in, int pos) {
-        int result =
-                ((in[pos    ] & 0xFF) << 24) |
-                        ((in[pos + 1] & 0xFF) << 16) |
-                        ((in[pos + 2] & 0xFF) <<  8) |
-                        ((in[pos + 3] & 0xFF) <<  0);
+        int result =    ((in[pos    ] & 0xFF) << 24) |
+                ((in[pos + 1] & 0xFF) << 16) |
+                ((in[pos + 2] & 0xFF) <<  8) |
+                ((in[pos + 3] & 0xFF) <<  0);
         return result;
     }
 
@@ -1238,4 +1279,4 @@ public class SettingsBackupAgent extends BackupAgentHelper {
         }
         return WifiManager.WIFI_STATE_UNKNOWN;
     }
-}
\ No newline at end of file
+}
index ef863e7..f278967 100644 (file)
@@ -5,7 +5,10 @@ include $(CLEAR_VARS)
 # Note we statically link SettingsState to do some unit tests.  It's not accessible otherwise
 # because this test is not an instrumentation test. (because the target runs in the system process.)
 LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-    ../src/com/android/providers/settings/SettingsState.java
+    ../src/com/android/providers/settings/SettingsState.java \
+    ../src/com/android/providers/settings/WiFiConfigurationSerializer.java \
+    ../src/com/android/providers/settings/NetworkPolicySerializer.java
+
 
 LOCAL_PACKAGE_NAME := SettingsProviderTest
 
@@ -13,4 +16,4 @@ LOCAL_MODULE_TAGS := tests
 
 LOCAL_CERTIFICATE := platform
 
-include $(BUILD_PACKAGE)
\ No newline at end of file
+include $(BUILD_PACKAGE)
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/NetworkPolicySerializerTest.java
new file mode 100644 (file)
index 0000000..1986596
--- /dev/null
@@ -0,0 +1,117 @@
+package com.android.providers.settings;
+
+import android.net.NetworkPolicy;
+import android.net.NetworkTemplate;
+import android.test.AndroidTestCase;
+
+import java.util.Random;
+
+/**
+ * Tests for NetworkPolicySerializer
+ */
+public class NetworkPolicySerializerTest extends AndroidTestCase {
+    static Random sRandom = new Random();
+
+    public void testMarshallAndUnmarshalNetworkPolicy() {
+        NetworkPolicy policy = getDummyNetworkPolicy();
+        byte[] data = NetworkPolicySerializer.marshalNetworkPolicy(policy);
+        assertNotNull("Got Null data from marshal", data);
+        assertFalse("Got back an empty byte[] from marshal", data.length == 0);
+
+        NetworkPolicy unmarshaled = NetworkPolicySerializer.unmarshalNetworkPolicy(data);
+        assertNotNull("Got Null data from unmarshaled", unmarshaled);
+        assertTrue("NetworkPolicy Marshall and Unmarshal Failed!", policy.equals(unmarshaled));
+    }
+
+    public void testMarshallNetworkPolicyEdgeCases() {
+        byte[] data = NetworkPolicySerializer.marshalNetworkPolicy(null);
+        assertNotNull("NetworkPolicy marshal returned null. Expected: byte[0]", data);
+        assertEquals("NetworkPolicy marshal returned incomplete byte array. Expected: byte[0]",
+                data.length, 0);
+    }
+
+    public void testUnmarshallNetworkPolicyEdgeCases() {
+        NetworkPolicy policy = NetworkPolicySerializer.unmarshalNetworkPolicy(null);
+        assertNull("Non null NetworkPolicy returned for null byte[] input", policy);
+
+        policy = NetworkPolicySerializer.unmarshalNetworkPolicy(new byte[0]);
+        assertNull("Non null NetworkPolicy returned for empty byte[] input", policy);
+
+        policy = NetworkPolicySerializer.unmarshalNetworkPolicy(new byte[]{10, 20, 30, 40, 50, 60});
+        assertNull("Non null NetworkPolicy returned for incomplete byte[] input", policy);
+    }
+
+    public void testMarshallAndUnmarshalNetworkPolicies() {
+        NetworkPolicy[] policies = getDummyNetworkPolicies(5);
+        byte[] data = NetworkPolicySerializer.marshalNetworkPolicies(policies);
+        assertNotNull("Got Null data from marshal", data);
+        assertFalse("Got back an empty byte[] from marshal", data.length == 0);
+
+        NetworkPolicy[] unmarshaled = NetworkPolicySerializer.unmarshalNetworkPolicies(data);
+        assertNotNull("Got Null data from unmarshaled", unmarshaled);
+        try {
+            for (int i = 0; i < policies.length; i++) {
+                assertTrue("NetworkPolicies Marshall and Unmarshal Failed!",
+                        policies[i].equals(unmarshaled[i]));
+            }
+        } catch (NullPointerException npe) {
+            assertTrue("Some policies were not marshaled/unmarshaled correctly", false);
+        }
+    }
+
+    public void testMarshallNetworkPoliciesEdgeCases() {
+        byte[] data = NetworkPolicySerializer.marshalNetworkPolicies(null);
+        assertNotNull("NetworkPolicies marshal returned null!", data);
+        assertEquals("NetworkPolicies marshal returned incomplete byte array", data.length, 0);
+
+        data = NetworkPolicySerializer.marshalNetworkPolicies(new NetworkPolicy[0]);
+        assertNotNull("NetworkPolicies marshal returned null for empty NetworkPolicy[]", data);
+        assertEquals("NetworkPolicies marshal returned incomplete byte array for empty NetworkPolicy[]"
+                , data.length, 0);
+    }
+
+    public void testUnmarshalNetworkPoliciesEdgeCases() {
+        NetworkPolicy[] policies = NetworkPolicySerializer.unmarshalNetworkPolicies(null);
+        assertNotNull("NetworkPolicies unmarshal returned null for null input. Expected: byte[0] ",
+                policies);
+        assertEquals("Non Empty NetworkPolicy[] returned for null input Expected: byte[0]",
+                policies.length, 0);
+
+        policies = NetworkPolicySerializer.unmarshalNetworkPolicies(new byte[0]);
+        assertNotNull("NetworkPolicies unmarshal returned null for empty byte[] input. Expected: byte[0]",
+                policies);
+        assertEquals("Non Empty NetworkPolicy[] returned for empty byte[] input. Expected: byte[0]",
+                policies.length, 0);
+
+        policies = NetworkPolicySerializer.unmarshalNetworkPolicies(new byte[]{10, 20, 30, 40, 50, 60});
+        assertNotNull("NetworkPolicies unmarshal returned null for incomplete byte[] input. " +
+                "Expected: byte[0] ", policies);
+        assertEquals("Non Empty NetworkPolicy[] returned for incomplete byte[] input Expected: byte[0]",
+                policies.length, 0);
+
+    }
+
+    private NetworkPolicy[] getDummyNetworkPolicies(int num) {
+        NetworkPolicy[] policies = new NetworkPolicy[num];
+        for (int i = 0; i < num; i++) {
+            policies[i] = getDummyNetworkPolicy();
+        }
+        return policies;
+    }
+
+    private NetworkPolicy getDummyNetworkPolicy() {
+        NetworkTemplate template = new NetworkTemplate(NetworkTemplate.MATCH_MOBILE_ALL, "subId",
+                "GoogleGuest");
+        int cycleDay = sRandom.nextInt();
+        String cycleTimezone = "timezone";
+        long warningBytes = sRandom.nextLong();
+        long limitBytes = sRandom.nextLong();
+        long lastWarningSnooze = sRandom.nextLong();
+        long lastLimitSnooze = sRandom.nextLong();
+        boolean metered = sRandom.nextInt() % 2 == 0;
+        boolean inferred = sRandom.nextInt() % 2 == 0;
+        return new NetworkPolicy(template, cycleDay, cycleTimezone, warningBytes, limitBytes,
+                lastWarningSnooze, lastLimitSnooze, metered, inferred);
+    }
+
+}