summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChalard Jean <jchalard@google.com>2020-05-29 12:40:54 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-05-29 12:40:54 +0000
commitc71f9fcd2c50ac21ce23a717e274b9d8800ea668 (patch)
tree9c57dbbca9f8baee4ab89644bfc5df75397e250b
parent4ebd0d5cfc0cc25605f3e2c87d02512bb84820f6 (diff)
parent1e2e741071140b5f911db91b2008bda8dbdb732e (diff)
Merge "Implement delete methods" into rvc-dev am: 1e2e741071
Change-Id: Idc718c8adadf76acb5a6c8157118bc86b1ce559a
-rw-r--r--common/networkstackclient/Android.bp1
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/.hash1
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStore.aidl30
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStoreCallbacks.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/Blob.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusAndCountListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusListener.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/NetworkAttributesParcelable.aidl26
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl24
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/StatusParcelable.aidl22
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl2
-rw-r--r--common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl22
-rw-r--r--common/networkstackclient/src/android/net/IIpMemoryStore.aidl41
-rw-r--r--common/networkstackclient/src/android/net/IpMemoryStoreClient.java59
-rw-r--r--common/networkstackclient/src/android/net/ipmemorystore/IOnStatusAndCountListener.aidl28
-rw-r--r--common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java16
-rw-r--r--common/networkstackclient/src/android/net/ipmemorystore/OnDeleteStatusListener.java57
-rw-r--r--src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java67
-rw-r--r--src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java57
-rw-r--r--src/com/android/server/connectivity/ipmemorystore/StatusAndCount.java29
-rw-r--r--tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java132
25 files changed, 771 insertions, 19 deletions
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index 43d482f..3ddf633 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -44,6 +44,7 @@ aidl_interface {
"4",
"5",
"6",
+ "7",
],
visibility: [
"//system/tools/aidl/build",
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/.hash b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/.hash
new file mode 100644
index 0000000..786a6f7
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/.hash
@@ -0,0 +1 @@
+31826566143ef882d67fac9f24566f73df4907b4
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..bf7a26d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+ oneway void factoryReset();
+ oneway void delete(String l2Key, boolean needWipe, android.net.ipmemorystore.IOnStatusAndCountListener listener);
+ oneway void deleteCluster(String cluster, boolean needWipe, android.net.ipmemorystore.IOnStatusAndCountListener listener);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..2024391
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..8a1b57e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+parcelable Blob {
+ byte[] data;
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..e711272
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..4abecb9
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..05c48b3
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..0bc8c5e
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusAndCountListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
new file mode 100644
index 0000000..cf30fa1
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnStatusAndCountListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status, int count);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..e71de47
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..92a570d
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String cluster;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..eca0987
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..7554608
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/7/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
index ac87e59..bf7a26d 100644
--- a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/IIpMemoryStore.aidl
@@ -25,4 +25,6 @@ interface IIpMemoryStore {
oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
oneway void factoryReset();
+ oneway void delete(String l2Key, boolean needWipe, android.net.ipmemorystore.IOnStatusAndCountListener listener);
+ oneway void deleteCluster(String cluster, boolean needWipe, android.net.ipmemorystore.IOnStatusAndCountListener listener);
}
diff --git a/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
new file mode 100644
index 0000000..cf30fa1
--- /dev/null
+++ b/common/networkstackclient/aidl_api/ipmemorystore-aidl-interfaces/current/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+/* @hide */
+interface IOnStatusAndCountListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status, int count);
+}
diff --git a/common/networkstackclient/src/android/net/IIpMemoryStore.aidl b/common/networkstackclient/src/android/net/IIpMemoryStore.aidl
index add221a..3bb58bf 100644
--- a/common/networkstackclient/src/android/net/IIpMemoryStore.aidl
+++ b/common/networkstackclient/src/android/net/IIpMemoryStore.aidl
@@ -22,6 +22,7 @@ import android.net.ipmemorystore.IOnBlobRetrievedListener;
import android.net.ipmemorystore.IOnL2KeyResponseListener;
import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.IOnSameL3NetworkResponseListener;
+import android.net.ipmemorystore.IOnStatusAndCountListener;
import android.net.ipmemorystore.IOnStatusListener;
/** {@hide} */
@@ -39,8 +40,7 @@ oneway interface IIpMemoryStore {
* @param attributes The attributes for this network.
* @param listener A listener that will be invoked to inform of the completion of this call,
* or null if the client is not interested in learning about success/failure.
- * @return (through the listener) The L2 key. This is useful if the L2 key was not specified.
- * If the call failed, the L2 key will be null.
+ * @return (through the listener) A status to indicate success or failure.
*/
void storeNetworkAttributes(String l2Key, in NetworkAttributesParcelable attributes,
IOnStatusListener listener);
@@ -115,4 +115,41 @@ oneway interface IIpMemoryStore {
* Delete all data because a factory reset operation is in progress.
*/
void factoryReset();
+
+ /**
+ * Delete a single entry.
+ *
+ * @param l2key The L2 key of the entry to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately. This makes the
+ * operation vastly more expensive as the database files will have to be copied
+ * and created again from the old files (see sqlite3 VACUUM operation for
+ * details) and makes no functional difference; only pass true if security or
+ * privacy demands this data must be removed from disk immediately.
+ * Note that this can fail for storage reasons. The passed listener will then
+ * receive an appropriate error status with the number of deleted rows.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * @return (through the listener) A status to indicate success and the number of deleted records
+ */
+ void delete(String l2Key, boolean needWipe, IOnStatusAndCountListener listener);
+
+ /**
+ * Delete all entries in a cluster.
+ *
+ * This method will delete all entries in the memory store that have the cluster attribute
+ * passed as an argument.
+ *
+ * @param cluster The cluster to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately. This makes the
+ * operation vastly more expensive as the database files will have to be copied
+ * and created again from the old files (see sqlite3 VACUUM operation for
+ * details) and makes no functional difference; only pass true if security or
+ * privacy demands this data must be removed from disk immediately.
+ * Note that this can fail for storage reasons. The passed listener will then
+ * receive an appropriate error status with the number of deleted rows.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * @return (through the listener) A status to indicate success and the number of deleted records
+ */
+ void deleteCluster(String cluster, boolean needWipe, IOnStatusAndCountListener listener);
}
diff --git a/common/networkstackclient/src/android/net/IpMemoryStoreClient.java b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
index 014b528..f269f9c 100644
--- a/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
+++ b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.net.ipmemorystore.Blob;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.OnBlobRetrievedListener;
+import android.net.ipmemorystore.OnDeleteStatusListener;
import android.net.ipmemorystore.OnL2KeyResponseListener;
import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.OnSameL3NetworkResponseListener;
@@ -214,6 +215,64 @@ public abstract class IpMemoryStoreClient {
}
/**
+ * Delete a single entry.
+ *
+ * @param l2Key The L2 key of the entry to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately. This makes the
+ * operation vastly more expensive as the database files will have to be copied
+ * and created again from the old files (see sqlite3 VACUUM operation for
+ * details) and makes no functional difference; only pass true if security or
+ * privacy demands this data must be removed from disk immediately.
+ * Note that this can fail for storage reasons. The passed listener will then
+ * receive an appropriate error status with the number of deleted rows.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * returns (through the listener) A status to indicate success and the number of deleted records
+ */
+ public void delete(@NonNull final String l2Key, final boolean needWipe,
+ @Nullable final OnDeleteStatusListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(() ->
+ service.delete(l2Key, needWipe, OnDeleteStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error deleting from the memory store",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN),
+ 0 /* deletedRecords */));
+ }
+ }
+
+ /**
+ * Delete all entries in a cluster.
+ *
+ * This method will delete all entries in the memory store that have the cluster attribute
+ * passed as an argument.
+ *
+ * @param cluster The cluster to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately. This makes the
+ * operation vastly more expensive as the database files will have to be copied
+ * and created again from the old files (see sqlite3 VACUUM operation for
+ * details) and makes no functional difference; only pass true if security or
+ * privacy demands this data must be removed from disk immediately.
+ * Note that this can fail for storage reasons. The passed listener will then
+ * receive an appropriate error status with the number of deleted rows.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * returns (through the listener) A status to indicate success and the number of deleted records
+ */
+ public void deleteCluster(@NonNull final String cluster, final boolean needWipe,
+ @Nullable final OnDeleteStatusListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.deleteCluster(cluster, needWipe,
+ OnDeleteStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error deleting from the memory store",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN),
+ 0 /* deletedRecords */));
+ }
+ }
+
+ /**
* Wipe the data in the database upon network factory reset.
*/
public void factoryReset() {
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusAndCountListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
new file mode 100644
index 0000000..c19b5c1
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusAndCountListener.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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 android.net.ipmemorystore;
+
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnStatusAndCountListener {
+ /**
+ * The operation has completed with the specified status, and supplied the passed count
+ * as call-specific additional data.
+ */
+ void onComplete(in StatusParcelable status, int count);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java
index 104ac79..2e444fe 100644
--- a/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java
+++ b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java
@@ -218,6 +218,22 @@ public class NetworkAttributes {
private Integer mMtu;
/**
+ * Constructs a new Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Constructs a Builder from the passed NetworkAttributes.
+ */
+ public Builder(@NonNull final NetworkAttributes attributes) {
+ mAssignedAddress = attributes.assignedV4Address;
+ mAssignedAddressExpiry = attributes.assignedV4AddressExpiry;
+ mCluster = attributes.cluster;
+ mDnsAddresses = new ArrayList<>(attributes.dnsAddresses);
+ mMtu = attributes.mtu;
+ }
+
+ /**
* Set the assigned address.
* @param assignedV4Address The assigned address.
* @return This builder.
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnDeleteStatusListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnDeleteStatusListener.java
new file mode 100644
index 0000000..7138877
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnDeleteStatusListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 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 android.net.ipmemorystore;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * A listener for the IpMemoryStore to return a status to a client.
+ * @hide
+ */
+public interface OnDeleteStatusListener {
+ /**
+ * The operation has completed with the specified status, and deleted the specified
+ * number of records. The operation can fail with a non-zero count of deleted rows as
+ * wipe requests may fail for lack of storage. See the documentation of each deletion
+ * method for details.
+ */
+ void onComplete(Status status, int deletedRecords);
+
+ /** Converts this OnDeleteStatusListener to a parcelable object */
+ @NonNull
+ static IOnStatusAndCountListener toAIDL(@Nullable final OnDeleteStatusListener listener) {
+ return new IOnStatusAndCountListener.Stub() {
+ @Override
+ public void onComplete(final StatusParcelable statusParcelable, int deletedRecords) {
+ if (null != listener) {
+ listener.onComplete(new Status(statusParcelable), deletedRecords);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ };
+ }
+}
diff --git a/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java b/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
index be338e5..0b05a5b 100644
--- a/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
+++ b/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreDatabase.java
@@ -602,6 +602,64 @@ public class IpMemoryStoreDatabase {
return bestKey;
}
+ /**
+ * Delete a single entry by key.
+ *
+ * If |needWipe| is true, the data will be wiped from disk immediately. Otherwise, it will
+ * only be marked deleted, and overwritten by subsequent writes or reclaimed during the next
+ * maintenance window.
+ * Note that wiping data is a very expensive operation. This is meant for clients that need
+ * this data gone from disk immediately for security reasons. Functionally it makes no
+ * difference at all.
+ */
+ static StatusAndCount delete(@NonNull final SQLiteDatabase db, @NonNull final String l2key,
+ final boolean needWipe) {
+ return deleteEntriesWithColumn(db,
+ NetworkAttributesContract.COLNAME_L2KEY, l2key, needWipe);
+ }
+
+ /**
+ * Delete all entries that have a particular cluster value.
+ *
+ * If |needWipe| is true, the data will be wiped from disk immediately. Otherwise, it will
+ * only be marked deleted, and overwritten by subsequent writes or reclaimed during the next
+ * maintenance window.
+ * Note that wiping data is a very expensive operation. This is meant for clients that need
+ * this data gone from disk immediately for security reasons. Functionally it makes no
+ * difference at all.
+ */
+ static StatusAndCount deleteCluster(@NonNull final SQLiteDatabase db,
+ @NonNull final String cluster, final boolean needWipe) {
+ return deleteEntriesWithColumn(db,
+ NetworkAttributesContract.COLNAME_CLUSTER, cluster, needWipe);
+ }
+
+ // Delete all entries where the given column has the given value.
+ private static StatusAndCount deleteEntriesWithColumn(@NonNull final SQLiteDatabase db,
+ @NonNull final String column, @NonNull final String value, final boolean needWipe) {
+ db.beginTransaction();
+ int deleted = 0;
+ try {
+ deleted = db.delete(NetworkAttributesContract.TABLENAME,
+ column + "= ?", new String[] { value });
+ db.setTransactionSuccessful();
+ } catch (SQLiteException e) {
+ Log.e(TAG, "Could not delete from the memory store", e);
+ // Unclear what might have happened ; deleting records is not supposed to be able
+ // to fail barring a syntax error in the SQL query.
+ return new StatusAndCount(Status.ERROR_UNKNOWN, 0);
+ } finally {
+ db.endTransaction();
+ }
+
+ if (needWipe) {
+ final int vacuumStatus = vacuum(db);
+ // This is a problem for the client : return the failure
+ if (Status.SUCCESS != vacuumStatus) return new StatusAndCount(vacuumStatus, deleted);
+ }
+ return new StatusAndCount(Status.SUCCESS, deleted);
+ }
+
// Drops all records that are expired. Relevance has decayed to zero of these records. Returns
// an int out of Status.{SUCCESS, ERROR_*}
static int dropAllExpiredRecords(@NonNull final SQLiteDatabase db) {
@@ -708,4 +766,13 @@ public class IpMemoryStoreDatabase {
final int columnIndex = cursor.getColumnIndex(columnName);
return (columnIndex >= 0) ? cursor.getLong(columnIndex) : defaultValue;
}
+ private static int vacuum(@NonNull final SQLiteDatabase db) {
+ try {
+ db.execSQL("VACUUM");
+ return Status.SUCCESS;
+ } catch (SQLiteException e) {
+ // Vacuuming may fail from lack of storage, because it makes a copy of the database.
+ return Status.ERROR_STORAGE;
+ }
+ }
}
diff --git a/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java b/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
index cd29e0d..ae9c875 100644
--- a/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
+++ b/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
@@ -33,6 +33,7 @@ import android.net.ipmemorystore.IOnBlobRetrievedListener;
import android.net.ipmemorystore.IOnL2KeyResponseListener;
import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.IOnSameL3NetworkResponseListener;
+import android.net.ipmemorystore.IOnStatusAndCountListener;
import android.net.ipmemorystore.IOnStatusListener;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.NetworkAttributesParcelable;
@@ -116,7 +117,11 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub {
// TODO : investigate replacing this scheme with a scheme where each thread has its own
// instance of the database, as it may be faster. It is likely however that IpMemoryStore
// operations are mostly IO-bound anyway, and additional contention is unlikely to bring
- // benefits. Alternatively, a read-write lock might increase throughput.
+ // benefits. Alternatively, a read-write lock might increase throughput. Also if doing
+ // this work, care must be taken around the privacy-preserving VACUUM operations as
+ // VACUUM will fail if there are other open transactions at the same time, and using
+ // multiple threads will open the possibility of this failure happening, threatening
+ // the privacy guarantees.
mExecutor = Executors.newSingleThreadExecutor();
RegularMaintenanceJobService.schedule(mContext, this);
}
@@ -405,6 +410,56 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub {
}
/**
+ * Delete a single entry.
+ *
+ * @param l2Key The L2 key of the entry to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately for security reasons.
+ * This is very expensive and makes no functional difference ; only pass
+ * true if security requires this data must be removed from disk immediately.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * returns (through the listener) A status to indicate success and the number of deleted records
+ */
+ public void delete(@NonNull final String l2Key, final boolean needWipe,
+ @Nullable final IOnStatusAndCountListener listener) {
+ mExecutor.execute(() -> {
+ try {
+ final StatusAndCount res = IpMemoryStoreDatabase.delete(mDb, l2Key, needWipe);
+ if (null != listener) listener.onComplete(makeStatus(res.status), res.count);
+ } catch (final RemoteException e) {
+ // Client at the other end died
+ }
+ });
+ }
+
+ /**
+ * Delete all entries in a cluster.
+ *
+ * This method will delete all entries in the memory store that have the cluster attribute
+ * passed as an argument.
+ *
+ * @param cluster The cluster to delete.
+ * @param needWipe Whether the data must be wiped from disk immediately for security reasons.
+ * This is very expensive and makes no functional difference ; only pass
+ * true if security requires this data must be removed from disk immediately.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * returns (through the listener) A status to indicate success and the number of deleted records
+ */
+ public void deleteCluster(@NonNull final String cluster, final boolean needWipe,
+ @Nullable final IOnStatusAndCountListener listener) {
+ mExecutor.execute(() -> {
+ try {
+ final StatusAndCount res =
+ IpMemoryStoreDatabase.deleteCluster(mDb, cluster, needWipe);
+ if (null != listener) listener.onComplete(makeStatus(res.status), res.count);
+ } catch (final RemoteException e) {
+ // Client at the other end died
+ }
+ });
+ }
+
+ /**
* Wipe the data in IpMemoryStore database upon network factory reset.
*/
@Override
diff --git a/src/com/android/server/connectivity/ipmemorystore/StatusAndCount.java b/src/com/android/server/connectivity/ipmemorystore/StatusAndCount.java
new file mode 100644
index 0000000..2cbe843
--- /dev/null
+++ b/src/com/android/server/connectivity/ipmemorystore/StatusAndCount.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 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.server.connectivity.ipmemorystore;
+
+/**
+ * Small data class to wrap a Status and an int.
+ */
+public class StatusAndCount {
+ public final int status;
+ public final int count;
+ public StatusAndCount(final int status, final int count) {
+ this.status = status;
+ this.count = count;
+ }
+}
diff --git a/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
index 533bbc3..c0bdc4c 100644
--- a/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -20,6 +20,7 @@ import static com.android.server.connectivity.ipmemorystore.RegularMaintenanceJo
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -33,6 +34,7 @@ import android.net.ipmemorystore.IOnBlobRetrievedListener;
import android.net.ipmemorystore.IOnL2KeyResponseListener;
import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener;
import android.net.ipmemorystore.IOnSameL3NetworkResponseListener;
+import android.net.ipmemorystore.IOnStatusAndCountListener;
import android.net.ipmemorystore.IOnStatusListener;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.ipmemorystore.NetworkAttributesParcelable;
@@ -44,6 +46,7 @@ import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.RemoteException;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -69,10 +72,13 @@ import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
/** Unit tests for {@link IpMemoryStoreService}. */
@@ -198,6 +204,32 @@ public class IpMemoryStoreServiceTest {
};
}
+ /** Helper method to make a vanilla IOnStatusAndCountListener */
+ private IOnStatusAndCountListener onDeleteStatus(BiConsumer<Status, Integer> functor) {
+ return new IOnStatusAndCountListener() {
+ @Override
+ public void onComplete(final StatusParcelable statusParcelable, final int deletedCount)
+ throws RemoteException {
+ functor.accept(new Status(statusParcelable), deletedCount);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ };
+ }
+
/** Helper method to make an IOnBlobRetrievedListener */
private interface OnBlobRetrievedListener {
void onBlobRetrieved(Status status, String l2Key, String name, byte[] data);
@@ -339,17 +371,18 @@ public class IpMemoryStoreServiceTest {
}
}
- // Helper method to store network attributes to database
- private void storeAttributes(final String l2Key, final NetworkAttributes na) {
- storeAttributes("Did not complete storing attributes", l2Key, na);
+ // Helper method to store network attributes to database. Returns the stored attributes.
+ private NetworkAttributes storeAttributes(final String l2Key, final NetworkAttributes na) {
+ return storeAttributes("Did not complete storing attributes", l2Key, na);
}
- private void storeAttributes(final String timeoutMessage, final String l2Key,
+ private NetworkAttributes storeAttributes(final String timeoutMessage, final String l2Key,
final NetworkAttributes na) {
doLatched(timeoutMessage, latch -> mService.storeNetworkAttributes(l2Key, na.toParcelable(),
onStatus(status -> {
assertTrue("Store not successful : " + status.resultCode, status.isSuccess());
latch.countDown();
})));
+ return na;
}
// Helper method to store blob data to database
@@ -546,28 +579,37 @@ public class IpMemoryStoreServiceTest {
})));
}
- @Test
- public void testFindL2Key() throws UnknownHostException {
+ private List<NetworkAttributes> storeFixture() throws Exception {
+ final ArrayList<NetworkAttributes> stored = new ArrayList<>();
final NetworkAttributes.Builder na = new NetworkAttributes.Builder();
na.setCluster("cluster0");
- storeAttributes(FAKE_KEYS[0], na.build());
+ stored.add(storeAttributes(FAKE_KEYS[0], na.build()));
na.setDnsAddresses(Arrays.asList(
new InetAddress[] {Inet6Address.getByName("8D56:9AF1::08EE:20F1")}));
- na.setMtu(219);
- storeAttributes(FAKE_KEYS[1], na.build());
+ na.setMtu(208);
+ stored.add(storeAttributes(FAKE_KEYS[1], na.build()));
na.setMtu(null);
na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
na.setDnsAddresses(Arrays.asList(
new InetAddress[] {Inet6Address.getByName("0A1C:2E40:480A::1CA6")}));
na.setCluster("cluster1");
- storeAttributes(FAKE_KEYS[2], na.build());
+ stored.add(storeAttributes(FAKE_KEYS[2], na.build()));
na.setMtu(219);
- storeAttributes(FAKE_KEYS[3], na.build());
+ stored.add(storeAttributes(FAKE_KEYS[3], na.build()));
+ na.setCluster(null);
na.setMtu(240);
- storeAttributes(FAKE_KEYS[4], na.build());
+ stored.add(storeAttributes(FAKE_KEYS[4], na.build()));
na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("5.6.7.8"));
- storeAttributes(FAKE_KEYS[5], na.build());
+ stored.add(storeAttributes(FAKE_KEYS[5], na.build()));
+ return stored;
+ }
+
+ @Test
+ public void testFindL2Key() throws Exception {
+ final List<NetworkAttributes> stored = storeFixture();
+ final NetworkAttributes.Builder na = new NetworkAttributes.Builder(
+ stored.get(stored.size() - 1));
// Matches key 5 exactly
doLatched("Did not finish finding L2Key", latch ->
@@ -589,6 +631,7 @@ public class IpMemoryStoreServiceTest {
})));
// Closest to key 3 (indeed, identical)
+ na.setCluster("cluster1");
na.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
na.setMtu(219);
doLatched("Did not finish finding L2Key", latch ->
@@ -620,13 +663,13 @@ public class IpMemoryStoreServiceTest {
latch.countDown();
})));
- // But changing the MTU makes this closer to key 4
- na.setMtu(240);
+ // But changing the MTU makes this closer to key 2
+ na.setMtu(208);
doLatched("Did not finish finding L2Key", latch ->
mService.findL2Key(na.build().toParcelable(), onL2KeyResponse((status, key) -> {
assertTrue("Retrieve network sameness not successful : " + status.resultCode,
status.isSuccess());
- assertEquals(FAKE_KEYS[4], key);
+ assertEquals(FAKE_KEYS[2], key);
latch.countDown();
})));
@@ -691,6 +734,63 @@ public class IpMemoryStoreServiceTest {
})));
}
+ private NetworkAttributes fetchAttributes(@NonNull final String l2Key) throws Exception {
+ final CompletableFuture<NetworkAttributes> f = new CompletableFuture<>();
+ mService.retrieveNetworkAttributes(l2Key, onNetworkAttributesRetrieved(
+ (status, key, attr) -> {
+ assertTrue("Retrieve network attributes not successful : "
+ + status.resultCode, status.isSuccess());
+ f.complete(attr);
+ }));
+ return f.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ private void delete(@NonNull final String l2Key) {
+ doLatched("Did not finish deleting", latch ->
+ mService.delete(l2Key, false /* needWipe */, onDeleteStatus((status, deleted) -> {
+ assertTrue("Deleting failed :" + status.resultCode, status.isSuccess());
+ assertEquals("Deleting count != 1 :" + deleted, 1, deleted.intValue());
+ latch.countDown();
+ })), LONG_TIMEOUT_MS);
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ storeFixture();
+
+ delete(FAKE_KEYS[0]);
+ delete(FAKE_KEYS[3]);
+
+ assertNull(fetchAttributes(FAKE_KEYS[0]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[1]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[2]));
+ assertNull(fetchAttributes(FAKE_KEYS[3]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[4]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[5]));
+ }
+
+ @Test
+ public void testDeleteCluster() throws Exception {
+ storeFixture();
+
+ doLatched("Did not finish deleting", latch ->
+ mService.deleteCluster("cluster1", false /* needWipe */,
+ onDeleteStatus((status, deletedCount) -> {
+ assertTrue("Delete failed : " + status.resultCode, status.isSuccess());
+ // The fixture stores 2 keys under "cluster1"
+ assertEquals("Unexpected deleted count : " + deletedCount,
+ 2, deletedCount.intValue());
+ latch.countDown();
+ })), LONG_TIMEOUT_MS);
+
+ assertNotNull(fetchAttributes(FAKE_KEYS[0]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[1]));
+ assertNull(fetchAttributes(FAKE_KEYS[2]));
+ assertNull(fetchAttributes(FAKE_KEYS[3]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[4]));
+ assertNotNull(fetchAttributes(FAKE_KEYS[5]));
+ }
+
@Test
public void testFullMaintenance() throws Exception {
copyTestData(mDbFile);