diff options
| author | 2019-01-11 03:44:45 -0800 | |
|---|---|---|
| committer | 2019-01-11 03:44:45 -0800 | |
| commit | 54d91e605ce4c6f5b825106c4eb9eea42956d728 (patch) | |
| tree | abb3505cbc42d07c8429cf7088f53789400aefd7 | |
| parent | d7f69a3de7b5adc8dda75b7e91afbe326702828b (diff) | |
| parent | 3627deac8817788b571d614d9119308937b3f0c2 (diff) | |
Merge changes from topic "IPMS1"
am: 3627deac88
Change-Id: I80fc9437a041de68ce16ae5e85189b5d48fe1c97
25 files changed, 1375 insertions, 12 deletions
diff --git a/Android.bp b/Android.bp index 8b3e259ef30e..8d0e1d30f8ca 100644 --- a/Android.bp +++ b/Android.bp @@ -697,6 +697,7 @@ java_defaults { "android.hardware.radio-V1.3-java", "android.hardware.radio-V1.4-java", "android.hardware.usb.gadget-V1.0-java", + "networkstack-aidl-interfaces-java", "netd_aidl_interface-java", ], @@ -826,12 +827,14 @@ aidl_interface { srcs: [ "core/java/android/net/INetworkMonitor.aidl", "core/java/android/net/INetworkMonitorCallbacks.aidl", + "core/java/android/net/IIpMemoryStore.aidl", "core/java/android/net/INetworkStackConnector.aidl", "core/java/android/net/INetworkStackStatusCallback.aidl", "core/java/android/net/PrivateDnsConfigParcel.aidl", "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl", "core/java/android/net/dhcp/IDhcpServer.aidl", "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl", + "core/java/android/net/ipmemorystore/**/*.aidl", ], api_dir: "aidl/networkstack", } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 15005d094af4..83c93fb3019c 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -82,8 +82,10 @@ import android.net.ConnectivityThread; import android.net.EthernetManager; import android.net.IConnectivityManager; import android.net.IEthernetManager; +import android.net.IIpMemoryStore; import android.net.IIpSecService; import android.net.INetworkPolicyManager; +import android.net.IpMemoryStore; import android.net.IpSecManager; import android.net.NetworkPolicyManager; import android.net.NetworkScoreManager; @@ -286,10 +288,21 @@ final class SystemServiceRegistry { registerService(Context.NETWORK_STACK_SERVICE, NetworkStack.class, new StaticServiceFetcher<NetworkStack>() { - @Override - public NetworkStack createService() { - return new NetworkStack(); - }}); + @Override + public NetworkStack createService() { + return new NetworkStack(); + }}); + + registerService(Context.IP_MEMORY_STORE_SERVICE, IpMemoryStore.class, + new CachedServiceFetcher<IpMemoryStore>() { + @Override + public IpMemoryStore createService(final ContextImpl ctx) + throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow( + Context.IP_MEMORY_STORE_SERVICE); + IIpMemoryStore service = IIpMemoryStore.Stub.asInterface(b); + return new IpMemoryStore(ctx, service); + }}); registerService(Context.IPSEC_SERVICE, IpSecManager.class, new CachedServiceFetcher<IpSecManager>() { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 81e72ccafe4d..9532f2bf9cd7 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3015,6 +3015,7 @@ public abstract class Context { VIBRATOR_SERVICE, //@hide: STATUS_BAR_SERVICE, CONNECTIVITY_SERVICE, + //@hide: IP_MEMORY_STORE_SERVICE, IPSEC_SERVICE, //@hide: UPDATE_LOCK_SERVICE, //@hide: NETWORKMANAGEMENT_SERVICE, @@ -3514,6 +3515,14 @@ public abstract class Context { /** * Use with {@link #getSystemService(String)} to retrieve a + * {@link android.net.IpMemoryStore} to store and read information about + * known networks. + * @hide + */ + public static final String IP_MEMORY_STORE_SERVICE = "ipmemorystore"; + + /** + * Use with {@link #getSystemService(String)} to retrieve a * {@link android.net.IpSecManager} for encrypting Sockets or Networks with * IPSec. * diff --git a/core/java/android/net/IIpMemoryStore.aidl b/core/java/android/net/IIpMemoryStore.aidl new file mode 100644 index 000000000000..6f88dec8dee9 --- /dev/null +++ b/core/java/android/net/IIpMemoryStore.aidl @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 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; + +import android.net.ipmemorystore.Blob; +import android.net.ipmemorystore.NetworkAttributesParcelable; +import android.net.ipmemorystore.IOnBlobRetrievedListener; +import android.net.ipmemorystore.IOnL2KeyResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; +import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnStatusListener; + +/** {@hide} */ +oneway interface IIpMemoryStore { + /** + * Store network attributes for a given L2 key. + * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to + * calling findL2Key with the attributes and storing in the returned value. + * + * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2 + * key and only care about grouping can pass a unique ID here like the ones + * generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low + * relevance of such a network will lead to it being evicted soon if it's not + * refreshed. Use findL2Key to try and find a similar L2Key to these attributes. + * @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. + */ + void storeNetworkAttributes(String l2Key, in NetworkAttributesParcelable attributes, + IOnStatusListener listener); + + /** + * Store a binary blob associated with an L2 key and a name. + * + * @param l2Key The L2 key for this network. + * @param clientId The ID of the client. + * @param name The name of this data. + * @param data The data to store. + * @param listener A listener 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 or failure. + */ + void storeBlob(String l2Key, String clientId, String name, in Blob data, + IOnStatusListener listener); + + /** + * Returns the best L2 key associated with the attributes. + * + * This will find a record that would be in the same group as the passed attributes. This is + * useful to choose the key for storing a sample or private data when the L2 key is not known. + * If multiple records are group-close to these attributes, the closest match is returned. + * If multiple records have the same closeness, the one with the smaller (unicode codepoint + * order) L2 key is returned. + * If no record matches these attributes, null is returned. + * + * @param attributes The attributes of the network to find. + * @param listener The listener that will be invoked to return the answer. + * @return (through the listener) The L2 key if one matched, or null. + */ + void findL2Key(in NetworkAttributesParcelable attributes, IOnL2KeyResponseListener listener); + + /** + * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point + * to the same L3 network. Group-closeness is used to determine this. + * + * @param l2Key1 The key for the first network. + * @param l2Key2 The key for the second network. + * @param listener The listener that will be invoked to return the answer. + * @return (through the listener) A SameL3NetworkResponse containing the answer and confidence. + */ + void isSameNetwork(String l2Key1, String l2Key2, IOnSameNetworkResponseListener listener); + + /** + * Retrieve the network attributes for a key. + * If no record is present for this key, this will return null attributes. + * + * @param l2Key The key of the network to query. + * @param listener The listener that will be invoked to return the answer. + * @return (through the listener) The network attributes and the L2 key associated with + * the query. + */ + void retrieveNetworkAttributes(String l2Key, IOnNetworkAttributesRetrieved listener); + + /** + * Retrieve previously stored private data. + * If no data was stored for this L2 key and name this will return null. + * + * @param l2Key The L2 key. + * @param clientId The id of the client that stored this data. + * @param name The name of the data. + * @param listener The listener that will be invoked to return the answer. + * @return (through the listener) The private data (or null), with the L2 key + * and the name of the data associated with the query. + */ + void retrieveBlob(String l2Key, String clientId, String name, + IOnBlobRetrievedListener listener); +} diff --git a/core/java/android/net/IpMemoryStore.java b/core/java/android/net/IpMemoryStore.java new file mode 100644 index 000000000000..b35f09743877 --- /dev/null +++ b/core/java/android/net/IpMemoryStore.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2018 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; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemService; +import android.content.Context; +import android.net.ipmemorystore.Blob; +import android.net.ipmemorystore.IOnBlobRetrievedListener; +import android.net.ipmemorystore.IOnL2KeyResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; +import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnStatusListener; +import android.net.ipmemorystore.NetworkAttributes; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +/** + * The interface for system components to access the IP memory store. + * @see com.android.server.net.ipmemorystore.IpMemoryStoreService + * @hide + */ +@SystemService(Context.IP_MEMORY_STORE_SERVICE) +public class IpMemoryStore { + @NonNull final Context mContext; + @NonNull final IIpMemoryStore mService; + + public IpMemoryStore(@NonNull final Context context, @NonNull final IIpMemoryStore service) { + mContext = Preconditions.checkNotNull(context, "missing context"); + mService = Preconditions.checkNotNull(service, "missing IIpMemoryStore"); + } + + /** + * Store network attributes for a given L2 key. + * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to + * calling findL2Key with the attributes and storing in the returned value. + * + * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2 + * key and only care about grouping can pass a unique ID here like the ones + * generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low + * relevance of such a network will lead to it being evicted soon if it's not + * refreshed. Use findL2Key to try and find a similar L2Key to these attributes. + * @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. + * Through the listener, returns the L2 key. This is useful if the L2 key was not specified. + * If the call failed, the L2 key will be null. + */ + public void storeNetworkAttributes(@NonNull final String l2Key, + @NonNull final NetworkAttributes attributes, + @Nullable final IOnStatusListener listener) { + try { + mService.storeNetworkAttributes(l2Key, attributes.toParcelable(), listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Store a binary blob associated with an L2 key and a name. + * + * @param l2Key The L2 key for this network. + * @param clientId The ID of the client. + * @param name The name of this data. + * @param data The data to store. + * @param listener A listener to inform of the completion of this call, or null if the client + * is not interested in learning about success/failure. + * Through the listener, returns a status to indicate success or failure. + */ + public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId, + @NonNull final String name, @NonNull final Blob data, + @Nullable final IOnStatusListener listener) { + try { + mService.storeBlob(l2Key, clientId, name, data, listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the best L2 key associated with the attributes. + * + * This will find a record that would be in the same group as the passed attributes. This is + * useful to choose the key for storing a sample or private data when the L2 key is not known. + * If multiple records are group-close to these attributes, the closest match is returned. + * If multiple records have the same closeness, the one with the smaller (unicode codepoint + * order) L2 key is returned. + * If no record matches these attributes, null is returned. + * + * @param attributes The attributes of the network to find. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the L2 key if one matched, or null. + */ + public void findL2Key(@NonNull final NetworkAttributes attributes, + @NonNull final IOnL2KeyResponseListener listener) { + try { + mService.findL2Key(attributes.toParcelable(), listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point + * to the same L3 network. Group-closeness is used to determine this. + * + * @param l2Key1 The key for the first network. + * @param l2Key2 The key for the second network. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, a SameL3NetworkResponse containing the answer and confidence. + */ + public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2, + @NonNull final IOnSameNetworkResponseListener listener) { + try { + mService.isSameNetwork(l2Key1, l2Key2, listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve the network attributes for a key. + * If no record is present for this key, this will return null attributes. + * + * @param l2Key The key of the network to query. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the network attributes and the L2 key associated with + * the query. + */ + public void retrieveNetworkAttributes(@NonNull final String l2Key, + @NonNull final IOnNetworkAttributesRetrieved listener) { + try { + mService.retrieveNetworkAttributes(l2Key, listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve previously stored private data. + * If no data was stored for this L2 key and name this will return null. + * + * @param l2Key The L2 key. + * @param clientId The id of the client that stored this data. + * @param name The name of the data. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the private data (or null), with the L2 key + * and the name of the data associated with the query. + */ + public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId, + @NonNull final String name, @NonNull final IOnBlobRetrievedListener listener) { + try { + mService.retrieveBlob(l2Key, clientId, name, listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/net/ipmemorystore/Blob.aidl b/core/java/android/net/ipmemorystore/Blob.aidl new file mode 100644 index 000000000000..9dbef117f8a4 --- /dev/null +++ b/core/java/android/net/ipmemorystore/Blob.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 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; + +/** + * A blob of data opaque to the memory store. The client mutates this at its own risk, + * and it is strongly suggested to never do it at all and treat this as immutable. + * {@hide} + */ +parcelable Blob { + byte[] data; +} diff --git a/core/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/core/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl new file mode 100644 index 000000000000..4926feb06e55 --- /dev/null +++ b/core/java/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 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.Blob; +import android.net.ipmemorystore.StatusParcelable; + +/** {@hide} */ +oneway interface IOnBlobRetrievedListener { + /** + * Private data was retrieved for the L2 key and name specified. + * Note this does not return the client ID, as clients are expected to only ever use one ID. + */ + void onBlobRetrieved(in StatusParcelable status, in String l2Key, in String name, + in Blob data); +} diff --git a/core/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/core/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl new file mode 100644 index 000000000000..dea0cc4e2586 --- /dev/null +++ b/core/java/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 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 IOnL2KeyResponseListener { + /** + * The operation completed with the specified L2 key. + */ + void onL2KeyResponse(in StatusParcelable status, in String l2Key); +} diff --git a/core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl b/core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl new file mode 100644 index 000000000000..57f59a17cfe7 --- /dev/null +++ b/core/java/android/net/ipmemorystore/IOnNetworkAttributesRetrieved.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 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.NetworkAttributesParcelable; +import android.net.ipmemorystore.StatusParcelable; + +/** {@hide} */ +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, + in NetworkAttributesParcelable attributes); +} diff --git a/core/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl b/core/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl new file mode 100644 index 000000000000..294bd3bd4012 --- /dev/null +++ b/core/java/android/net/ipmemorystore/IOnSameNetworkResponseListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 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.SameL3NetworkResponseParcelable; +import android.net.ipmemorystore.StatusParcelable; + +/** {@hide} */ +oneway interface IOnSameNetworkResponseListener { + /** + * The memory store has come up with the answer to a query that was sent. + */ + void onSameNetworkResponse(in StatusParcelable status, + in SameL3NetworkResponseParcelable response); +} diff --git a/core/java/android/net/ipmemorystore/IOnStatusListener.aidl b/core/java/android/net/ipmemorystore/IOnStatusListener.aidl new file mode 100644 index 000000000000..5d0750449ec5 --- /dev/null +++ b/core/java/android/net/ipmemorystore/IOnStatusListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 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 IOnStatusListener { + /** + * The operation has completed with the specified status. + */ + void onComplete(in StatusParcelable status); +} diff --git a/core/java/android/net/ipmemorystore/NetworkAttributes.java b/core/java/android/net/ipmemorystore/NetworkAttributes.java new file mode 100644 index 000000000000..d7e5b2761e58 --- /dev/null +++ b/core/java/android/net/ipmemorystore/NetworkAttributes.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2018 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; + +import com.android.internal.annotations.VisibleForTesting; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * A POD object to represent attributes of a single L2 network entry. + * @hide + */ +public class NetworkAttributes { + private static final boolean DBG = true; + + // 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; + + // 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; + + // The list of DNS server addresses. + @Nullable + public final List<InetAddress> dnsAddresses; + + // The mtu on this network. + @Nullable + public final Integer mtu; + + NetworkAttributes( + @Nullable final Inet4Address assignedV4Address, + @Nullable final String groupHint, + @Nullable final List<InetAddress> dnsAddresses, + @Nullable final Integer mtu) { + if (mtu != null && mtu < 0) throw new IllegalArgumentException("MTU can't be negative"); + this.assignedV4Address = assignedV4Address; + this.groupHint = groupHint; + this.dnsAddresses = null == dnsAddresses ? null : + Collections.unmodifiableList(new ArrayList<>(dnsAddresses)); + this.mtu = mtu; + } + + @VisibleForTesting + public NetworkAttributes(@NonNull final NetworkAttributesParcelable parcelable) { + // The call to the other constructor must be the first statement of this constructor, + // so everything has to be inline + this((Inet4Address) getByAddressOrNull(parcelable.assignedV4Address), + parcelable.groupHint, + blobArrayToInetAddressList(parcelable.dnsAddresses), + parcelable.mtu >= 0 ? parcelable.mtu : null); + } + + @Nullable + private static InetAddress getByAddressOrNull(@Nullable final byte[] address) { + try { + return InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + return null; + } + } + + @Nullable + private static List<InetAddress> blobArrayToInetAddressList(@Nullable final Blob[] blobs) { + if (null == blobs) return null; + final ArrayList<InetAddress> list = new ArrayList<>(blobs.length); + for (final Blob b : blobs) { + final InetAddress addr = getByAddressOrNull(b.data); + if (null != addr) list.add(addr); + } + return list; + } + + @Nullable + private static Blob[] inetAddressListToBlobArray(@Nullable final List<InetAddress> addresses) { + if (null == addresses) return null; + final ArrayList<Blob> blobs = new ArrayList<>(); + for (int i = 0; i < addresses.size(); ++i) { + final InetAddress addr = addresses.get(i); + if (null == addr) continue; + final Blob b = new Blob(); + b.data = addr.getAddress(); + blobs.add(b); + } + return blobs.toArray(new Blob[0]); + } + + /** Converts this NetworkAttributes to a parcelable object */ + @NonNull + public NetworkAttributesParcelable toParcelable() { + final NetworkAttributesParcelable parcelable = new NetworkAttributesParcelable(); + parcelable.assignedV4Address = + (null == assignedV4Address) ? null : assignedV4Address.getAddress(); + parcelable.groupHint = groupHint; + parcelable.dnsAddresses = inetAddressListToBlobArray(dnsAddresses); + parcelable.mtu = (null == mtu) ? -1 : mtu; + return parcelable; + } + + /** @hide */ + public static class Builder { + @Nullable + private Inet4Address mAssignedAddress; + @Nullable + private String mGroupHint; + @Nullable + private List<InetAddress> mDnsAddresses; + @Nullable + private Integer mMtu; + + /** + * Set the assigned address. + * @param assignedV4Address The assigned address. + * @return This builder. + */ + public Builder setAssignedV4Address(@Nullable final Inet4Address assignedV4Address) { + mAssignedAddress = assignedV4Address; + return this; + } + + /** + * Set the group hint. + * @param groupHint The group hint. + * @return This builder. + */ + public Builder setGroupHint(@Nullable final String groupHint) { + mGroupHint = groupHint; + return this; + } + + /** + * Set the DNS addresses. + * @param dnsAddresses The DNS addresses. + * @return This builder. + */ + public Builder setDnsAddresses(@Nullable final List<InetAddress> dnsAddresses) { + if (DBG && null != dnsAddresses) { + // Parceling code crashes if one of the addresses is null, therefore validate + // them when running in debug. + for (final InetAddress address : dnsAddresses) { + if (null == address) throw new IllegalArgumentException("Null DNS address"); + } + } + this.mDnsAddresses = dnsAddresses; + return this; + } + + /** + * Set the MTU. + * @param mtu The MTU. + * @return This builder. + */ + public Builder setMtu(@Nullable final Integer mtu) { + if (null != mtu && mtu < 0) throw new IllegalArgumentException("MTU can't be negative"); + mMtu = mtu; + return this; + } + + /** + * Return the built NetworkAttributes object. + * @return The built NetworkAttributes object. + */ + public NetworkAttributes build() { + return new NetworkAttributes(mAssignedAddress, mGroupHint, mDnsAddresses, mMtu); + } + } + + @Override + public boolean equals(@Nullable final Object o) { + if (!(o instanceof NetworkAttributes)) return false; + final NetworkAttributes other = (NetworkAttributes) o; + return Objects.equals(assignedV4Address, other.assignedV4Address) + && Objects.equals(groupHint, other.groupHint) + && Objects.equals(dnsAddresses, other.dnsAddresses) + && Objects.equals(mtu, other.mtu); + } + + @Override + public int hashCode() { + return Objects.hash(assignedV4Address, groupHint, dnsAddresses, mtu); + } +} diff --git a/core/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/core/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl new file mode 100644 index 000000000000..0894d7260915 --- /dev/null +++ b/core/java/android/net/ipmemorystore/NetworkAttributesParcelable.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 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; + +// Blob[] is used to represent an array of byte[], as structured AIDL does not support arrays +// of arrays. +import android.net.ipmemorystore.Blob; + +/** + * An object to represent attributes of a single L2 network entry. + * See NetworkAttributes.java for a description of each field. The types used in this class + * are structured parcelable types instead of the richer types of the NetworkAttributes object, + * but they have the same purpose. The NetworkAttributes.java file also contains the code + * to convert the richer types to the parcelable types and back. + * @hide + */ +parcelable NetworkAttributesParcelable { + byte[] assignedV4Address; + String groupHint; + Blob[] dnsAddresses; + int mtu; +} diff --git a/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java b/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java new file mode 100644 index 000000000000..0cb37e9f75b4 --- /dev/null +++ b/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2018 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.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; + +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * An object representing the answer to a query whether two given L2 networks represent the + * same L3 network. Parcels as a SameL3NetworkResponseParceled object. + * @hide + */ +public class SameL3NetworkResponse { + @IntDef(prefix = "NETWORK_", + value = {NETWORK_SAME, NETWORK_DIFFERENT, NETWORK_NEVER_CONNECTED}) + @Retention(RetentionPolicy.SOURCE) + public @interface NetworkSameness {} + + /** + * Both L2 networks represent the same L3 network. + */ + public static final int NETWORK_SAME = 1; + + /** + * The two L2 networks represent a different L3 network. + */ + public static final int NETWORK_DIFFERENT = 2; + + /** + * The device has never connected to at least one of these two L2 networks, or data + * has been wiped. Therefore the device has never seen the L3 network behind at least + * one of these two L2 networks, and can't evaluate whether it's the same as the other. + */ + public static final int NETWORK_NEVER_CONNECTED = 3; + + /** + * The first L2 key specified in the query. + */ + @NonNull + public final String l2Key1; + + /** + * The second L2 key specified in the query. + */ + @NonNull + public final String l2Key2; + + /** + * A confidence value indicating whether the two L2 networks represent the same L3 network. + * + * If both L2 networks were known, this value will be between 0.0 and 1.0, with 0.0 + * representing complete confidence that the given L2 networks represent a different + * L3 network, and 1.0 representing complete confidence that the given L2 networks + * represent the same L3 network. + * If at least one of the L2 networks was not known, this value will be outside of the + * 0.0~1.0 range. + * + * Most apps should not be interested in this, and are encouraged to use the collapsing + * {@link #getNetworkSameness()} function below. + */ + public final float confidence; + + /** + * @return whether the two L2 networks represent the same L3 network. Either + * {@code NETWORK_SAME}, {@code NETWORK_DIFFERENT} or {@code NETWORK_NEVER_CONNECTED}. + */ + @NetworkSameness + public final int getNetworkSameness() { + if (confidence > 1.0 || confidence < 0.0) return NETWORK_NEVER_CONNECTED; + return confidence > 0.5 ? NETWORK_SAME : NETWORK_DIFFERENT; + } + + SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2, + final float confidence) { + this.l2Key1 = l2Key1; + this.l2Key2 = l2Key2; + this.confidence = confidence; + } + + /** Builds a SameL3NetworkResponse from a parcelable object */ + @VisibleForTesting + public SameL3NetworkResponse(@NonNull final SameL3NetworkResponseParcelable parceled) { + this(parceled.l2Key1, parceled.l2Key2, parceled.confidence); + } + + /** Converts this SameL3NetworkResponse to a parcelable object */ + @NonNull + public SameL3NetworkResponseParcelable toParcelable() { + final SameL3NetworkResponseParcelable parcelable = new SameL3NetworkResponseParcelable(); + parcelable.l2Key1 = l2Key1; + parcelable.l2Key2 = l2Key2; + parcelable.confidence = confidence; + return parcelable; + } + + // Note key1 and key2 have to match each other for this to return true. If + // key1 matches o.key2 and the other way around this returns false. + @Override + public boolean equals(@Nullable final Object o) { + if (!(o instanceof SameL3NetworkResponse)) return false; + final SameL3NetworkResponse other = (SameL3NetworkResponse) o; + return l2Key1.equals(other.l2Key1) && l2Key2.equals(other.l2Key2) + && confidence == other.confidence; + } + + @Override + public int hashCode() { + return Objects.hash(l2Key1, l2Key2, confidence); + } +} diff --git a/core/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/core/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl new file mode 100644 index 000000000000..71966998a68a --- /dev/null +++ b/core/java/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 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; + +/** {@hide} */ +parcelable SameL3NetworkResponseParcelable { + String l2Key1; + String l2Key2; + float confidence; +} diff --git a/core/java/android/net/ipmemorystore/Status.java b/core/java/android/net/ipmemorystore/Status.java new file mode 100644 index 000000000000..5b016ec55ae1 --- /dev/null +++ b/core/java/android/net/ipmemorystore/Status.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2018 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 parcelable status representing the result of an operation. + * Parcels as StatusParceled. + * @hide + */ +public class Status { + public static final int SUCCESS = 0; + + public final int resultCode; + + public Status(final int resultCode) { + this.resultCode = resultCode; + } + + Status(@NonNull final StatusParcelable parcelable) { + this(parcelable.resultCode); + } + + /** Converts this Status to a parcelable object */ + @NonNull + public StatusParcelable toParcelable() { + final StatusParcelable parcelable = new StatusParcelable(); + parcelable.resultCode = resultCode; + return parcelable; + } + + public boolean isSuccess() { + return SUCCESS == resultCode; + } +} diff --git a/core/java/android/net/ipmemorystore/StatusParcelable.aidl b/core/java/android/net/ipmemorystore/StatusParcelable.aidl new file mode 100644 index 000000000000..fb36ef4a56ff --- /dev/null +++ b/core/java/android/net/ipmemorystore/StatusParcelable.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2018 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; + +/** {@hide} */ +parcelable StatusParcelable { + int resultCode; +} diff --git a/services/Android.bp b/services/Android.bp index bea51be321c9..a416ca0b6977 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -23,6 +23,7 @@ java_library { "services.companion", "services.coverage", "services.devicepolicy", + "services.ipmemorystore", "services.midi", "services.net", "services.print", diff --git a/services/ipmemorystore/Android.bp b/services/ipmemorystore/Android.bp new file mode 100644 index 000000000000..013cf5616904 --- /dev/null +++ b/services/ipmemorystore/Android.bp @@ -0,0 +1,4 @@ +java_library_static { + name: "services.ipmemorystore", + srcs: ["java/**/*.java"], +} diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java new file mode 100644 index 000000000000..c9759bf6170f --- /dev/null +++ b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 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.net.ipmemorystore; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Context; +import android.net.IIpMemoryStore; +import android.net.ipmemorystore.Blob; +import android.net.ipmemorystore.IOnBlobRetrievedListener; +import android.net.ipmemorystore.IOnL2KeyResponseListener; +import android.net.ipmemorystore.IOnNetworkAttributesRetrieved; +import android.net.ipmemorystore.IOnSameNetworkResponseListener; +import android.net.ipmemorystore.IOnStatusListener; +import android.net.ipmemorystore.NetworkAttributesParcelable; + +/** + * Implementation for the IP memory store. + * This component offers specialized services for network components to store and retrieve + * knowledge about networks, and provides intelligence that groups level 2 networks together + * into level 3 networks. + * + * @hide + */ +public class IpMemoryStoreService extends IIpMemoryStore.Stub { + final Context mContext; + + public IpMemoryStoreService(@NonNull final Context context) { + mContext = context; + } + + /** + * Store network attributes for a given L2 key. + * + * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2 + * key and only care about grouping can pass a unique ID here like the ones + * generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low + * relevance of such a network will lead to it being evicted soon if it's not + * refreshed. Use findL2Key to try and find a similar L2Key to these attributes. + * @param attributes The attributes for this network. + * @param listener A listener to inform of the completion of this call, or null if the client + * is not interested in learning about success/failure. + * Through the listener, returns the L2 key. This is useful if the L2 key was not specified. + * If the call failed, the L2 key will be null. + */ + @Override + public void storeNetworkAttributes(@NonNull final String l2Key, + @NonNull final NetworkAttributesParcelable attributes, + @Nullable final IOnStatusListener listener) { + // TODO : implement this + } + + /** + * Store a binary blob associated with an L2 key and a name. + * + * @param l2Key The L2 key for this network. + * @param clientId The ID of the client. + * @param name The name of this data. + * @param data The data to store. + * @param listener The listener that will be invoked to return the answer, or null if the + * is not interested in learning about success/failure. + * Through the listener, returns a status to indicate success or failure. + */ + @Override + public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId, + @NonNull final String name, @NonNull final Blob data, + @Nullable final IOnStatusListener listener) { + // TODO : implement this + } + + /** + * Returns the best L2 key associated with the attributes. + * + * This will find a record that would be in the same group as the passed attributes. This is + * useful to choose the key for storing a sample or private data when the L2 key is not known. + * If multiple records are group-close to these attributes, the closest match is returned. + * If multiple records have the same closeness, the one with the smaller (unicode codepoint + * order) L2 key is returned. + * If no record matches these attributes, null is returned. + * + * @param attributes The attributes of the network to find. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the L2 key if one matched, or null. + */ + @Override + public void findL2Key(@NonNull final NetworkAttributesParcelable attributes, + @NonNull final IOnL2KeyResponseListener listener) { + // TODO : implement this + } + + /** + * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point + * to the same L3 network. Group-closeness is used to determine this. + * + * @param l2Key1 The key for the first network. + * @param l2Key2 The key for the second network. + * @param listener The listener that will be invoked to return the answer. + * 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 + } + + /** + * Retrieve the network attributes for a key. + * If no record is present for this key, this will return null attributes. + * + * @param l2Key The key of the network to query. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the network attributes and the L2 key associated with + * the query. + */ + @Override + public void retrieveNetworkAttributes(@NonNull final String l2Key, + @NonNull final IOnNetworkAttributesRetrieved listener) { + // TODO : implement this. + } + + /** + * Retrieve previously stored private data. + * If no data was stored for this L2 key and name this will return null. + * + * @param l2Key The L2 key. + * @param clientId The id of the client that stored this data. + * @param name The name of the data. + * @param listener The listener that will be invoked to return the answer. + * Through the listener, returns the private data if any or null if none, with the L2 key + * and the name of the data associated with the query. + */ + @Override + public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId, + @NonNull final String name, @NonNull final IOnBlobRetrievedListener listener) { + // TODO : implement this. + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2d07fd6c6442..479fb9a89200 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -16,6 +16,13 @@ package com.android.server; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; +import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; +import static android.os.IServiceManager.DUMP_FLAG_PROTO; +import static android.view.Display.DEFAULT_DISPLAY; + +import android.annotation.NonNull; import android.app.ActivityThread; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; @@ -84,11 +91,12 @@ import com.android.server.job.JobSchedulerService; import com.android.server.lights.LightsService; import com.android.server.media.MediaResourceMonitorService; import com.android.server.media.MediaRouterService; -import com.android.server.media.MediaUpdateService; import com.android.server.media.MediaSessionService; +import com.android.server.media.MediaUpdateService; import com.android.server.media.projection.MediaProjectionManagerService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; +import com.android.server.net.ipmemorystore.IpMemoryStoreService; import com.android.server.net.watchlist.NetworkWatchlistService; import com.android.server.notification.NotificationManagerService; import com.android.server.oemlock.OemLockService; @@ -133,12 +141,6 @@ import java.util.Timer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH; -import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; -import static android.os.IServiceManager.DUMP_FLAG_PROTO; -import static android.view.Display.DEFAULT_DISPLAY; - public final class SystemServer { private static final String TAG = "SystemServer"; @@ -1098,6 +1100,15 @@ public final class SystemServer { } traceEnd(); + traceBeginAndSlog("StartIpMemoryStoreService"); + try { + ServiceManager.addService(Context.IP_MEMORY_STORE_SERVICE, + new IpMemoryStoreService(context)); + } catch (Throwable e) { + reportWtf("starting IP Memory Store Service", e); + } + traceEnd(); + traceBeginAndSlog("StartIpSecService"); try { ipSecService = IpSecService.create(context); @@ -1981,7 +1992,7 @@ public final class SystemServer { windowManager.onSystemUiStarted(); } - private static void traceBeginAndSlog(String name) { + private static void traceBeginAndSlog(@NonNull String name) { Slog.i(TAG, name); BOOT_TIMINGS_TRACE_LOG.traceBegin(name); } diff --git a/tests/net/Android.mk b/tests/net/Android.mk index 9d1edbf1eaf0..f6f35fdadcd1 100644 --- a/tests/net/Android.mk +++ b/tests/net/Android.mk @@ -18,6 +18,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ mockito-target-minus-junit4 \ platform-test-annotations \ services.core \ + services.ipmemorystore \ services.net LOCAL_JAVA_LIBRARIES := \ diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java new file mode 100644 index 000000000000..eae9710215ca --- /dev/null +++ b/tests/net/java/android/net/IpMemoryStoreTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 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; + +import android.content.Context; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class IpMemoryStoreTest { + @Mock + Context mMockContext; + @Mock + IIpMemoryStore mMockService; + IpMemoryStore mStore; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mStore = new IpMemoryStore(mMockContext, mMockService); + } + + @Test + public void testNetworkAttributes() { + // TODO : implement this + } + + @Test + public void testPrivateData() { + // TODO : implement this + } + + @Test + public void testFindL2Key() { + // TODO : implement this + } + + @Test + public void testIsSameNetwork() { + // TODO : implement this + } + +} diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java new file mode 100644 index 000000000000..a9f9758bb1f8 --- /dev/null +++ b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import android.os.Parcel; +import android.os.Parcelable; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.util.Arrays; +import java.util.Collections; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ParcelableTests { + @Test + public void testNetworkAttributesParceling() throws Exception { + final NetworkAttributes.Builder builder = new NetworkAttributes.Builder(); + NetworkAttributes in = builder.build(); + assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); + + builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4")); + // groupHint stays null this time around + builder.setDnsAddresses(Collections.emptyList()); + builder.setMtu(18); + in = builder.build(); + assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); + + builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("6.7.8.9")); + builder.setGroupHint("groupHint"); + builder.setDnsAddresses(Arrays.asList( + InetAddress.getByName("ACA1:652B:0911:DE8F:1200:115E:913B:AA2A"), + InetAddress.getByName("6.7.8.9"))); + builder.setMtu(1_000_000); + in = builder.build(); + assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); + + builder.setMtu(null); + in = builder.build(); + assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable()))); + } + + @Test + public void testPrivateDataParceling() throws Exception { + final Blob in = new Blob(); + in.data = new byte[] {89, 111, 108, 111}; + final Blob out = parcelingRoundTrip(in); + // Object.equals on byte[] tests the references + assertEquals(in.data.length, out.data.length); + assertTrue(Arrays.equals(in.data, out.data)); + } + + @Test + public void testSameL3NetworkResponseParceling() throws Exception { + final SameL3NetworkResponseParcelable parcelable = new SameL3NetworkResponseParcelable(); + parcelable.l2Key1 = "key 1"; + parcelable.l2Key2 = "key 2"; + parcelable.confidence = 0.43f; + + final SameL3NetworkResponse in = new SameL3NetworkResponse(parcelable); + assertEquals("key 1", in.l2Key1); + assertEquals("key 2", in.l2Key2); + assertEquals(0.43f, in.confidence, 0.01f /* delta */); + + final SameL3NetworkResponse out = + new SameL3NetworkResponse(parcelingRoundTrip(in.toParcelable())); + + assertEquals(in, out); + assertEquals(in.l2Key1, out.l2Key1); + assertEquals(in.l2Key2, out.l2Key2); + assertEquals(in.confidence, out.confidence, 0.01f /* delta */); + } + + private <T extends Parcelable> T parcelingRoundTrip(final T in) throws Exception { + final Parcel p = Parcel.obtain(); + in.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + final byte[] marshalledData = p.marshall(); + p.recycle(); + + final Parcel q = Parcel.obtain(); + q.unmarshall(marshalledData, 0, marshalledData.length); + q.setDataPosition(0); + + final Parcelable.Creator<T> creator = (Parcelable.Creator<T>) + in.getClass().getField("CREATOR").get(null); // static object, so null receiver + final T unmarshalled = (T) creator.createFromParcel(q); + q.recycle(); + return unmarshalled; + } +} diff --git a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java new file mode 100644 index 000000000000..859a54d29321 --- /dev/null +++ b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2018 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.net.ipmemorystore; + +import android.content.Context; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link IpMemoryStoreServiceTest}. */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class IpMemoryStoreServiceTest { + @Mock + Context mMockContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testNetworkAttributes() { + final IpMemoryStoreService service = new IpMemoryStoreService(mMockContext); + // TODO : implement this + } + + @Test + public void testPrivateData() { + final IpMemoryStoreService service = new IpMemoryStoreService(mMockContext); + // TODO : implement this + } + + @Test + public void testFindL2Key() { + final IpMemoryStoreService service = new IpMemoryStoreService(mMockContext); + // TODO : implement this + } + + @Test + public void testIsSameNetwork() { + final IpMemoryStoreService service = new IpMemoryStoreService(mMockContext); + // TODO : implement this + } +} |