Loading core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,6 @@ oneway interface IOnNetworkAttributesRetrieved { * Network attributes were fetched for the specified L2 key. While the L2 key will never * be null, the attributes may be if no data is stored about this L2 key. */ void onL2KeyResponse(in StatusParcelable status, in String l2Key, void onNetworkAttributesRetrieved(in StatusParcelable status, in String l2Key, in NetworkAttributesParcelable attributes); } core/java/android/net/ipmemorystore/NetworkAttributes.java +59 −1 Original line number Diff line number Diff line Loading @@ -37,27 +37,57 @@ import java.util.StringJoiner; public class NetworkAttributes { private static final boolean DBG = true; // Weight cutoff for grouping. To group, a similarity score is computed with the following // algorithm : if both fields are non-null and equals() then add their assigned weight, else if // both are null then add a portion of their assigned weight (see NULL_MATCH_WEIGHT), // otherwise add nothing. // As a guideline, this should be something like 60~75% of the total weights in this class. The // design states "in essence a reader should imagine that if two important columns don't match, // or one important and several unimportant columns don't match then the two records are // considered a different group". private static final float TOTAL_WEIGHT_CUTOFF = 520.0f; // The portion of the weight that is earned when scoring group-sameness by having both columns // being null. This is because some networks rightfully don't have some attributes (e.g. a // V6-only network won't have an assigned V4 address) and both being null should count for // something, but attributes may also be null just because data is unavailable. private static final float NULL_MATCH_WEIGHT = 0.25f; // The v4 address that was assigned to this device the last time it joined this network. // This typically comes from DHCP but could be something else like static configuration. // This does not apply to IPv6. // TODO : add a list of v6 prefixes for the v6 case. @Nullable public final Inet4Address assignedV4Address; private static final float WEIGHT_ASSIGNEDV4ADDR = 300.0f; // Optionally supplied by the client if it has an opinion on L3 network. For example, this // could be a hash of the SSID + security type on WiFi. @Nullable public final String groupHint; private static final float WEIGHT_GROUPHINT = 300.0f; // The list of DNS server addresses. @Nullable public final List<InetAddress> dnsAddresses; private static final float WEIGHT_DNSADDRESSES = 200.0f; // The mtu on this network. @Nullable public final Integer mtu; private static final float WEIGHT_MTU = 50.0f; // The sum of all weights in this class. Tests ensure that this stays equal to the total of // all weights. /** @hide */ @VisibleForTesting public static final float TOTAL_WEIGHT = WEIGHT_ASSIGNEDV4ADDR + WEIGHT_GROUPHINT + WEIGHT_DNSADDRESSES + WEIGHT_MTU; NetworkAttributes( /** @hide */ @VisibleForTesting public NetworkAttributes( @Nullable final Inet4Address assignedV4Address, @Nullable final String groupHint, @Nullable final List<InetAddress> dnsAddresses, Loading Loading @@ -126,6 +156,34 @@ public class NetworkAttributes { return parcelable; } private float samenessContribution(final float weight, @Nullable final Object o1, @Nullable final Object o2) { if (null == o1) { return (null == o2) ? weight * NULL_MATCH_WEIGHT : 0f; } return Objects.equals(o1, o2) ? weight : 0f; } /** @hide */ public float getNetworkGroupSamenessConfidence(@NonNull final NetworkAttributes o) { final float samenessScore = samenessContribution(WEIGHT_ASSIGNEDV4ADDR, assignedV4Address, o.assignedV4Address) + samenessContribution(WEIGHT_GROUPHINT, groupHint, o.groupHint) + samenessContribution(WEIGHT_DNSADDRESSES, dnsAddresses, o.dnsAddresses) + samenessContribution(WEIGHT_MTU, mtu, o.mtu); // The minimum is 0, the max is TOTAL_WEIGHT and should be represented by 1.0, and // TOTAL_WEIGHT_CUTOFF should represent 0.5, but there is no requirement that // TOTAL_WEIGHT_CUTOFF would be half of TOTAL_WEIGHT (indeed, it should not be). // So scale scores under the cutoff between 0 and 0.5, and the scores over the cutoff // between 0.5 and 1.0. if (samenessScore < TOTAL_WEIGHT_CUTOFF) { return samenessScore / (TOTAL_WEIGHT_CUTOFF * 2); } else { return (samenessScore - TOTAL_WEIGHT_CUTOFF) / (TOTAL_WEIGHT - TOTAL_WEIGHT_CUTOFF) / 2 + 0.5f; } } /** @hide */ public static class Builder { @Nullable Loading core/java/android/net/ipmemorystore/SameL3NetworkResponse.java +2 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,8 @@ public class SameL3NetworkResponse { return confidence > 0.5 ? NETWORK_SAME : NETWORK_DIFFERENT; } SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2, /** @hide */ public SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2, final float confidence) { this.l2Key1 = l2Key1; this.l2Key2 = l2Key2; Loading services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java +12 −3 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * 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. Loading Loading @@ -134,12 +134,14 @@ public class IpMemoryStoreDatabase { } /** Called when the database is created */ @Override public void onCreate(@NonNull final SQLiteDatabase db) { db.execSQL(NetworkAttributesContract.CREATE_TABLE); db.execSQL(PrivateDataContract.CREATE_TABLE); } /** Called when the database is upgraded */ @Override public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) { // No upgrade supported yet. Loading @@ -149,6 +151,7 @@ public class IpMemoryStoreDatabase { } /** Called when the database is downgraded */ @Override public void onDowngrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) { // Downgrades always nuke all data and recreate an empty table. Loading Loading @@ -247,7 +250,9 @@ public class IpMemoryStoreDatabase { // result here. 0 results means the key was not found. if (cursor.getCount() != 1) return EXPIRY_ERROR; cursor.moveToFirst(); return cursor.getLong(0); // index in the EXPIRY_COLUMN array final long result = cursor.getLong(0); // index in the EXPIRY_COLUMN array cursor.close(); return result; } static final int RELEVANCE_ERROR = -1; // Legal values for relevance are positive Loading Loading @@ -321,6 +326,8 @@ public class IpMemoryStoreDatabase { final byte[] dnsAddressesBlob = getBlob(cursor, NetworkAttributesContract.COLNAME_DNSADDRESSES); final int mtu = getInt(cursor, NetworkAttributesContract.COLNAME_MTU, -1); cursor.close(); if (0 != assignedV4AddressInt) { builder.setAssignedV4Address(NetworkUtils.intToInet4AddressHTH(assignedV4AddressInt)); } Loading Loading @@ -353,7 +360,9 @@ public class IpMemoryStoreDatabase { // get more than one result here. 0 results means the key was not found. if (cursor.getCount() != 1) return null; cursor.moveToFirst(); return cursor.getBlob(0); // index in the DATA_COLUMN array final byte[] result = cursor.getBlob(0); // index in the DATA_COLUMN array cursor.close(); return result; } // Helper methods Loading services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java +41 −8 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.net.ipmemorystore.IOnSameNetworkResponseListener; import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; import android.net.ipmemorystore.NetworkAttributesParcelable; import android.net.ipmemorystore.SameL3NetworkResponse; import android.net.ipmemorystore.Status; import android.net.ipmemorystore.StatusParcelable; import android.net.ipmemorystore.Utils; Loading Loading @@ -264,9 +265,40 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { * Through the listener, a SameL3NetworkResponse containing the answer and confidence. */ @Override public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2, @NonNull final IOnSameNetworkResponseListener listener) { // TODO : implement this. public void isSameNetwork(@Nullable final String l2Key1, @Nullable final String l2Key2, @Nullable final IOnSameNetworkResponseListener listener) { if (null == listener) return; mExecutor.execute(() -> { try { if (null == l2Key1 || null == l2Key2) { listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } if (null == mDb) { listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } try { final NetworkAttributes attr1 = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key1); final NetworkAttributes attr2 = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key2); if (null == attr1 || null == attr2) { listener.onSameNetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, -1f /* never connected */).toParcelable()); return; } final float confidence = attr1.getNetworkGroupSamenessConfidence(attr2); listener.onSameNetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, confidence).toParcelable()); } catch (Exception e) { listener.onSameNetworkResponse(makeStatus(ERROR_GENERIC), null); } } catch (final RemoteException e) { // Client at the other end died } }); } /** Loading @@ -285,21 +317,22 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { mExecutor.execute(() -> { try { if (null == l2Key) { listener.onL2KeyResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), l2Key, null); listener.onNetworkAttributesRetrieved( makeStatus(ERROR_ILLEGAL_ARGUMENT), l2Key, null); return; } if (null == mDb) { listener.onL2KeyResponse(makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED), l2Key, null); listener.onNetworkAttributesRetrieved( makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED), l2Key, null); return; } try { final NetworkAttributes attributes = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key); listener.onL2KeyResponse(makeStatus(SUCCESS), l2Key, listener.onNetworkAttributesRetrieved(makeStatus(SUCCESS), l2Key, null == attributes ? null : attributes.toParcelable()); } catch (final Exception e) { listener.onL2KeyResponse(makeStatus(ERROR_GENERIC), l2Key, null); listener.onNetworkAttributesRetrieved(makeStatus(ERROR_GENERIC), l2Key, null); } } catch (final RemoteException e) { // Client at the other end died Loading Loading
core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,6 @@ oneway interface IOnNetworkAttributesRetrieved { * Network attributes were fetched for the specified L2 key. While the L2 key will never * be null, the attributes may be if no data is stored about this L2 key. */ void onL2KeyResponse(in StatusParcelable status, in String l2Key, void onNetworkAttributesRetrieved(in StatusParcelable status, in String l2Key, in NetworkAttributesParcelable attributes); }
core/java/android/net/ipmemorystore/NetworkAttributes.java +59 −1 Original line number Diff line number Diff line Loading @@ -37,27 +37,57 @@ import java.util.StringJoiner; public class NetworkAttributes { private static final boolean DBG = true; // Weight cutoff for grouping. To group, a similarity score is computed with the following // algorithm : if both fields are non-null and equals() then add their assigned weight, else if // both are null then add a portion of their assigned weight (see NULL_MATCH_WEIGHT), // otherwise add nothing. // As a guideline, this should be something like 60~75% of the total weights in this class. The // design states "in essence a reader should imagine that if two important columns don't match, // or one important and several unimportant columns don't match then the two records are // considered a different group". private static final float TOTAL_WEIGHT_CUTOFF = 520.0f; // The portion of the weight that is earned when scoring group-sameness by having both columns // being null. This is because some networks rightfully don't have some attributes (e.g. a // V6-only network won't have an assigned V4 address) and both being null should count for // something, but attributes may also be null just because data is unavailable. private static final float NULL_MATCH_WEIGHT = 0.25f; // The v4 address that was assigned to this device the last time it joined this network. // This typically comes from DHCP but could be something else like static configuration. // This does not apply to IPv6. // TODO : add a list of v6 prefixes for the v6 case. @Nullable public final Inet4Address assignedV4Address; private static final float WEIGHT_ASSIGNEDV4ADDR = 300.0f; // Optionally supplied by the client if it has an opinion on L3 network. For example, this // could be a hash of the SSID + security type on WiFi. @Nullable public final String groupHint; private static final float WEIGHT_GROUPHINT = 300.0f; // The list of DNS server addresses. @Nullable public final List<InetAddress> dnsAddresses; private static final float WEIGHT_DNSADDRESSES = 200.0f; // The mtu on this network. @Nullable public final Integer mtu; private static final float WEIGHT_MTU = 50.0f; // The sum of all weights in this class. Tests ensure that this stays equal to the total of // all weights. /** @hide */ @VisibleForTesting public static final float TOTAL_WEIGHT = WEIGHT_ASSIGNEDV4ADDR + WEIGHT_GROUPHINT + WEIGHT_DNSADDRESSES + WEIGHT_MTU; NetworkAttributes( /** @hide */ @VisibleForTesting public NetworkAttributes( @Nullable final Inet4Address assignedV4Address, @Nullable final String groupHint, @Nullable final List<InetAddress> dnsAddresses, Loading Loading @@ -126,6 +156,34 @@ public class NetworkAttributes { return parcelable; } private float samenessContribution(final float weight, @Nullable final Object o1, @Nullable final Object o2) { if (null == o1) { return (null == o2) ? weight * NULL_MATCH_WEIGHT : 0f; } return Objects.equals(o1, o2) ? weight : 0f; } /** @hide */ public float getNetworkGroupSamenessConfidence(@NonNull final NetworkAttributes o) { final float samenessScore = samenessContribution(WEIGHT_ASSIGNEDV4ADDR, assignedV4Address, o.assignedV4Address) + samenessContribution(WEIGHT_GROUPHINT, groupHint, o.groupHint) + samenessContribution(WEIGHT_DNSADDRESSES, dnsAddresses, o.dnsAddresses) + samenessContribution(WEIGHT_MTU, mtu, o.mtu); // The minimum is 0, the max is TOTAL_WEIGHT and should be represented by 1.0, and // TOTAL_WEIGHT_CUTOFF should represent 0.5, but there is no requirement that // TOTAL_WEIGHT_CUTOFF would be half of TOTAL_WEIGHT (indeed, it should not be). // So scale scores under the cutoff between 0 and 0.5, and the scores over the cutoff // between 0.5 and 1.0. if (samenessScore < TOTAL_WEIGHT_CUTOFF) { return samenessScore / (TOTAL_WEIGHT_CUTOFF * 2); } else { return (samenessScore - TOTAL_WEIGHT_CUTOFF) / (TOTAL_WEIGHT - TOTAL_WEIGHT_CUTOFF) / 2 + 0.5f; } } /** @hide */ public static class Builder { @Nullable Loading
core/java/android/net/ipmemorystore/SameL3NetworkResponse.java +2 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,8 @@ public class SameL3NetworkResponse { return confidence > 0.5 ? NETWORK_SAME : NETWORK_DIFFERENT; } SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2, /** @hide */ public SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2, final float confidence) { this.l2Key1 = l2Key1; this.l2Key2 = l2Key2; Loading
services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java +12 −3 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * 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. Loading Loading @@ -134,12 +134,14 @@ public class IpMemoryStoreDatabase { } /** Called when the database is created */ @Override public void onCreate(@NonNull final SQLiteDatabase db) { db.execSQL(NetworkAttributesContract.CREATE_TABLE); db.execSQL(PrivateDataContract.CREATE_TABLE); } /** Called when the database is upgraded */ @Override public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) { // No upgrade supported yet. Loading @@ -149,6 +151,7 @@ public class IpMemoryStoreDatabase { } /** Called when the database is downgraded */ @Override public void onDowngrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) { // Downgrades always nuke all data and recreate an empty table. Loading Loading @@ -247,7 +250,9 @@ public class IpMemoryStoreDatabase { // result here. 0 results means the key was not found. if (cursor.getCount() != 1) return EXPIRY_ERROR; cursor.moveToFirst(); return cursor.getLong(0); // index in the EXPIRY_COLUMN array final long result = cursor.getLong(0); // index in the EXPIRY_COLUMN array cursor.close(); return result; } static final int RELEVANCE_ERROR = -1; // Legal values for relevance are positive Loading Loading @@ -321,6 +326,8 @@ public class IpMemoryStoreDatabase { final byte[] dnsAddressesBlob = getBlob(cursor, NetworkAttributesContract.COLNAME_DNSADDRESSES); final int mtu = getInt(cursor, NetworkAttributesContract.COLNAME_MTU, -1); cursor.close(); if (0 != assignedV4AddressInt) { builder.setAssignedV4Address(NetworkUtils.intToInet4AddressHTH(assignedV4AddressInt)); } Loading Loading @@ -353,7 +360,9 @@ public class IpMemoryStoreDatabase { // get more than one result here. 0 results means the key was not found. if (cursor.getCount() != 1) return null; cursor.moveToFirst(); return cursor.getBlob(0); // index in the DATA_COLUMN array final byte[] result = cursor.getBlob(0); // index in the DATA_COLUMN array cursor.close(); return result; } // Helper methods Loading
services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java +41 −8 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.net.ipmemorystore.IOnSameNetworkResponseListener; import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; import android.net.ipmemorystore.NetworkAttributesParcelable; import android.net.ipmemorystore.SameL3NetworkResponse; import android.net.ipmemorystore.Status; import android.net.ipmemorystore.StatusParcelable; import android.net.ipmemorystore.Utils; Loading Loading @@ -264,9 +265,40 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { * Through the listener, a SameL3NetworkResponse containing the answer and confidence. */ @Override public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2, @NonNull final IOnSameNetworkResponseListener listener) { // TODO : implement this. public void isSameNetwork(@Nullable final String l2Key1, @Nullable final String l2Key2, @Nullable final IOnSameNetworkResponseListener listener) { if (null == listener) return; mExecutor.execute(() -> { try { if (null == l2Key1 || null == l2Key2) { listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } if (null == mDb) { listener.onSameNetworkResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), null); return; } try { final NetworkAttributes attr1 = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key1); final NetworkAttributes attr2 = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key2); if (null == attr1 || null == attr2) { listener.onSameNetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, -1f /* never connected */).toParcelable()); return; } final float confidence = attr1.getNetworkGroupSamenessConfidence(attr2); listener.onSameNetworkResponse(makeStatus(SUCCESS), new SameL3NetworkResponse(l2Key1, l2Key2, confidence).toParcelable()); } catch (Exception e) { listener.onSameNetworkResponse(makeStatus(ERROR_GENERIC), null); } } catch (final RemoteException e) { // Client at the other end died } }); } /** Loading @@ -285,21 +317,22 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub { mExecutor.execute(() -> { try { if (null == l2Key) { listener.onL2KeyResponse(makeStatus(ERROR_ILLEGAL_ARGUMENT), l2Key, null); listener.onNetworkAttributesRetrieved( makeStatus(ERROR_ILLEGAL_ARGUMENT), l2Key, null); return; } if (null == mDb) { listener.onL2KeyResponse(makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED), l2Key, null); listener.onNetworkAttributesRetrieved( makeStatus(ERROR_DATABASE_CANNOT_BE_OPENED), l2Key, null); return; } try { final NetworkAttributes attributes = IpMemoryStoreDatabase.retrieveNetworkAttributes(mDb, l2Key); listener.onL2KeyResponse(makeStatus(SUCCESS), l2Key, listener.onNetworkAttributesRetrieved(makeStatus(SUCCESS), l2Key, null == attributes ? null : attributes.toParcelable()); } catch (final Exception e) { listener.onL2KeyResponse(makeStatus(ERROR_GENERIC), l2Key, null); listener.onNetworkAttributesRetrieved(makeStatus(ERROR_GENERIC), l2Key, null); } } catch (final RemoteException e) { // Client at the other end died Loading