Implement the IpMemoryStore APIs that retrieve or store the network event count.
Bug: 329010113
Test: TH
Change-Id: I911129127c4467e72c30b608a91ff086e3784f1a
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index 2c031e3..004ec09 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -172,7 +172,7 @@
enabled: false,
},
},
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
// TODO: have tethering depend on networkstack-client and set visibility to private
visibility: [
"//system/tools/aidl/build",
@@ -183,43 +183,43 @@
// Remove old networkstack aidl interface version info that is no longer used.
{
version: "13",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "14",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "15",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "16",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "17",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "18",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "19",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "20",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "21",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
{
version: "22",
- imports: ["ipmemorystore-aidl-interfaces-V10"],
+ imports: ["ipmemorystore-aidl-interfaces-V11"],
},
],
@@ -231,7 +231,7 @@
sdk_version: "system_current",
min_sdk_version: "30",
static_libs: [
- "ipmemorystore-aidl-interfaces-V10-java",
+ "ipmemorystore-aidl-interfaces-V11-java",
"networkstack-aidl-interfaces-V22-java",
],
visibility: ["//packages/modules/NetworkStack:__subpackages__"],
diff --git a/common/networkstackclient/src/android/net/IpMemoryStoreClient.java b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
index a1c5694..8b93124 100644
--- a/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
+++ b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
@@ -25,6 +25,7 @@
import android.net.ipmemorystore.OnDeleteStatusListener;
import android.net.ipmemorystore.OnL2KeyResponseListener;
import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
+import android.net.ipmemorystore.OnNetworkEventCountRetrievedListener;
import android.net.ipmemorystore.OnSameL3NetworkResponseListener;
import android.net.ipmemorystore.OnStatusListener;
import android.net.ipmemorystore.Status;
@@ -289,4 +290,64 @@
Log.e(TAG, "Error executing factory reset", m);
}
}
+
+ /**
+ * Retrieve the specific network event counts for a given cluster and event type since one or
+ * more timestamps in the past.
+ *
+ * @param cluster The cluster to query.
+ * @param sinceTimes An array of timestamps in the past. The query will return an array of
+ * equal size. Each element in the array will contain the number of network
+ * events between the corresponding timestamp and the current time, e.g. query
+ * since the last week and/or the last day.
+ * @param eventTypes An array of network event types to query, which can be one or more of the
+ * above NETWORK_EVENT constants.
+ * @param listener The listener that will be invoked to return the answer.
+ * returns (through the listener) The event counts associated with the query, or an empty array
+ * if the query failed.
+ */
+ public void retrieveNetworkEventCount(@NonNull final String cluster,
+ @NonNull final long[] sinceTimes,
+ @NonNull final int[] eventTypes,
+ @Nullable final OnNetworkEventCountRetrievedListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveNetworkEventCount(cluster, sinceTimes, eventTypes,
+ OnNetworkEventCountRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving network event count",
+ () -> listener.onNetworkEventCountRetrieved(
+ new Status(Status.ERROR_UNKNOWN),
+ new int[0]) /* empty counts */);
+ }
+ }
+
+ /**
+ * Store a specific network event to database for a given cluster.
+ *
+ * @param cluster The cluster representing a notion of network group (e.g., BSSIDs with the
+ * same SSID).
+ * @param timestamp The timestamp {@link System.currentTimeMillis} when a specific network
+ * event occurred.
+ * @param expiry The timestamp {@link System.currentTimeMillis} when a specific network
+ * event stored in the database expires, e.g. it might be one week from now.
+ * @param eventType One of the NETWORK_EVENT constants above.
+ * @param listener A listener that will be invoked to inform of the completion of this call.
+ * returns (through the listener) A status to indicate success or failure.
+ */
+ public void storeNetworkEvent(@NonNull final String cluster,
+ final long timestamp,
+ final long expiry,
+ final int eventType,
+ @Nullable final OnStatusListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeNetworkEvent(cluster, timestamp, expiry, eventType,
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ if (null == listener) return;
+ ignoringRemoteException("Error storing network event",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
+ }
+ }
}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkEventCountRetrievedListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkEventCountRetrievedListener.java
new file mode 100644
index 0000000..1c30150
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkEventCountRetrievedListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2024 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;
+
+/**
+ * A listener for the IpMemoryStore to return specific network event counts.
+ * @hide
+ */
+public interface OnNetworkEventCountRetrievedListener {
+ /**
+ * The memory store has come up with the answer to a query that was sent.
+ */
+ void onNetworkEventCountRetrieved(Status status, int[] counts);
+
+ /** Converts this OnNetworkEventCountRetrievedListener to a parcelable object */
+ @NonNull
+ static IOnNetworkEventCountRetrievedListener toAIDL(
+ @NonNull final OnNetworkEventCountRetrievedListener listener) {
+ return new IOnNetworkEventCountRetrievedListener.Stub() {
+ @Override
+ public void onNetworkEventCountRetrieved(
+ final StatusParcelable statusParcelable,
+ final int[] counts) {
+ // NonNull, but still don't crash the system server if null
+ if (null != listener) {
+ listener.onNetworkEventCountRetrieved(new Status(statusParcelable), counts);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ };
+ }
+}
diff --git a/src/com/android/networkstack/ipmemorystore/IpMemoryStoreDatabase.java b/src/com/android/networkstack/ipmemorystore/IpMemoryStoreDatabase.java
index 9e7df82..e6dd9cd 100644
--- a/src/com/android/networkstack/ipmemorystore/IpMemoryStoreDatabase.java
+++ b/src/com/android/networkstack/ipmemorystore/IpMemoryStoreDatabase.java
@@ -749,6 +749,19 @@
}
}
+ static int storeNetworkEvent(@NonNull final SQLiteDatabase db, @NonNull final String cluster,
+ final long timestamp, final long expiry, final int eventType) {
+ // TODO: implement this.
+ return Status.SUCCESS;
+ }
+
+ static int[] retrieveNetworkEventCount(@NonNull final SQLiteDatabase db,
+ @NonNull final String cluster, @NonNull final long[] sinceTimes,
+ @NonNull final int[] eventTypes) {
+ // TODO: implement this.
+ return new int[0];
+ }
+
// Helper methods
private static String getString(final Cursor cursor, final String columnName) {
final int columnIndex = cursor.getColumnIndex(columnName);
diff --git a/src/com/android/networkstack/ipmemorystore/IpMemoryStoreService.java b/src/com/android/networkstack/ipmemorystore/IpMemoryStoreService.java
index 76ed56c..a05c5cb 100644
--- a/src/com/android/networkstack/ipmemorystore/IpMemoryStoreService.java
+++ b/src/com/android/networkstack/ipmemorystore/IpMemoryStoreService.java
@@ -32,6 +32,7 @@
import android.net.ipmemorystore.IOnBlobRetrievedListener;
import android.net.ipmemorystore.IOnL2KeyResponseListener;
import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener;
+import android.net.ipmemorystore.IOnNetworkEventCountRetrievedListener;
import android.net.ipmemorystore.IOnSameL3NetworkResponseListener;
import android.net.ipmemorystore.IOnStatusAndCountListener;
import android.net.ipmemorystore.IOnStatusListener;
@@ -484,6 +485,95 @@
});
}
+ /**
+ * Retrieve the specific network event counts for a given cluster and event type since one or
+ * more timestamps in the past.
+ *
+ * @param cluster The cluster to query.
+ * @param sinceTimes An array of timestamps in the past. The query will return an array of
+ * equal size. Each element in the array will contain the number of network
+ * events between the corresponding timestamp and the current time, e.g. query
+ * since the last week and/or the last day.
+ * @param eventTypes An array of network event types to query, which can be one or more of the
+ * above NETWORK_EVENT constants.
+ * @param listener The listener that will be invoked to return the answer.
+ * returns (through the listener) The event counts associated with the query, or an empty array
+ * if the query failed.
+ */
+ @Override
+ public void retrieveNetworkEventCount(@NonNull final String cluster,
+ @NonNull final long[] sinceTimes,
+ @NonNull final int[] eventTypes,
+ @Nullable final IOnNetworkEventCountRetrievedListener listener) {
+ if (null == listener) return;
+ mExecutor.execute(() -> {
+ try {
+ if (null == cluster) {
+ listener.onNetworkEventCountRetrieved(
+ makeStatus(ERROR_ILLEGAL_ARGUMENT), new int[0] /* counts */);
+ return;
+ }
+ if (null == mDb) {
+ listener.onNetworkEventCountRetrieved(
+ makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED), new int[0] /* counts */);
+ return;
+ }
+ try {
+ final int[] counts = IpMemoryStoreDatabase.retrieveNetworkEventCount(mDb,
+ cluster, sinceTimes, eventTypes);
+ listener.onNetworkEventCountRetrieved(makeStatus(SUCCESS), counts);
+ } catch (final Exception e) {
+ listener.onNetworkEventCountRetrieved(makeStatus(ERROR_GENERIC),
+ new int[0] /* counts */);
+ }
+ } catch (final RemoteException e) {
+ // Client at the other end died
+ }
+ });
+ }
+
+ /**
+ * Store a specific network event to database for a given cluster.
+ *
+ * @param cluster The cluster representing a notion of network group (e.g., BSSIDs with the
+ * same SSID).
+ * @param timestamp The timestamp {@link System.currentTimeMillis} when a specific network
+ * event occurred.
+ * @param expiry The timestamp {@link System.currentTimeMillis} when a specific network
+ * event stored in the database expires, e.g. it might be one week from now.
+ * @param eventType One of the NETWORK_EVENT constants above.
+ * @param listener A listener that will be invoked to inform of the completion of this call.
+ * returns (through the listener) A status to indicate success or failure.
+ */
+ @Override
+ public void storeNetworkEvent(@NonNull final String cluster,
+ final long timestamp,
+ final long expiry,
+ final int eventType,
+ @Nullable final IOnStatusListener listener) {
+ mExecutor.execute(() -> {
+ try {
+ if (null == cluster) {
+ listener.onComplete(makeStatus(ERROR_ILLEGAL_ARGUMENT));
+ return;
+ }
+ if (null == mDb) {
+ listener.onComplete(makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED));
+ return;
+ }
+ try {
+ final int code = IpMemoryStoreDatabase.storeNetworkEvent(mDb, cluster,
+ timestamp, expiry, eventType);
+ if (null != listener) listener.onComplete(makeStatus(code));
+ } catch (final Exception e) {
+ if (null != listener) listener.onComplete(makeStatus(ERROR_GENERIC));
+ }
+ } catch (final RemoteException e) {
+ // Client at the other end died
+ }
+ });
+ }
+
/** Get db size threshold. */
@VisibleForTesting
protected int getDbSizeThreshold() {