Merge "Add DnsSdTxtRecord to common net static library"
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index ffc02c3..2c707ab 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -12,9 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// File group "net-utils-framework-common-srcs" is also compiled into android framework.
-// Add jarjar rules here so that anything outside of framework could use this library
-// directly.
+// 1. The "net-utils-framework-common" library is also compiled into the framework and placed on the
+// boot classpath. It uses jarjar rules so that anything outside the framework can use this
+// library directly.
+// 2. The "net-utils-services-common" library is for use by modules and frameworks/base/services.
+// It does not need to be jarjared because it is not placed on the bootclasspath.
+// 3. The "net-utils-telephony-common-srcs" filegroup is for use specifically by telephony, which
+// places many of its classes, even non-API service classes, on the boot classpath. Any file that
+// is added to this filegroup *must* have a corresponding jarjar rule in the telephony jarjar
+// rules file. Otherwise, it will end up on the boot classpath and other modules will not be able
+// to provide their own copy.
filegroup {
name: "net-utils-framework-common-srcs",
@@ -24,7 +31,13 @@
java_library {
name: "net-utils-framework-common",
- srcs: [":net-utils-framework-common-srcs" ],
+ srcs: [
+ ":net-utils-framework-common-srcs",
+ // TODO: avoid including all framework annotations as they end up in library users jars
+ // and need jarjaring
+ ":framework-annotations",
+ ],
+ sdk_version: "system_current",
jarjar_rules: "jarjar-rules-shared.txt",
visibility: [
"//frameworks/base/packages/Tethering",
@@ -35,3 +48,33 @@
"//packages/modules/CaptivePortalLogin",
]
}
+
+java_library {
+ name: "net-utils-services-common",
+ srcs: [
+ "src_servicescommon/**/*.java",
+ ":framework-annotations",
+ ],
+ sdk_version: "system_current",
+ visibility: [
+ "//frameworks/base/services/net",
+ "//frameworks/base/packages/Tethering",
+ "//frameworks/opt/net/wifi/service",
+ "//frameworks/opt/net/ike",
+ "//packages/modules/NetworkStack",
+ "//packages/modules/CaptivePortalLogin",
+ ],
+}
+
+// Use a filegroup and not a library for telephony sources, as framework-annotations cannot be
+// included either (some annotations would be duplicated on the bootclasspath).
+filegroup {
+ name: "net-utils-telephony-common-srcs",
+ srcs: [
+ // Any class here *must* have a corresponding jarjar rule in the telephony build rules.
+ "src_servicescommon/android/net/NetworkFactory.java",
+ ],
+ visibility: [
+ "//frameworks/opt/telephony",
+ ],
+}
diff --git a/staticlibs/jarjar-rules-shared.txt b/staticlibs/jarjar-rules-shared.txt
index 4a2b653..b22771d 100644
--- a/staticlibs/jarjar-rules-shared.txt
+++ b/staticlibs/jarjar-rules-shared.txt
@@ -1 +1,3 @@
rule android.net.util.** com.android.net.module.util.@1
+rule android.annotation.** com.android.net.module.annotation.@1
+rule com.android.internal.annotations.** com.android.net.module.annotation.@1
\ No newline at end of file
diff --git a/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java b/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
index 5345789..e71f8fb 100644
--- a/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
+++ b/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
@@ -20,11 +20,9 @@
import android.annotation.Nullable;
import android.net.MacAddress;
-import com.android.internal.util.BitUtils;
-import com.android.internal.util.Preconditions;
-
import java.security.SecureRandom;
import java.util.Arrays;
+import java.util.Objects;
import java.util.Random;
/**
@@ -98,14 +96,15 @@
* Convert a byte address to long address.
*/
public static long longAddrFromByteAddr(byte[] addr) {
- Preconditions.checkNotNull(addr);
+ Objects.requireNonNull(addr);
if (!isMacAddress(addr)) {
throw new IllegalArgumentException(
Arrays.toString(addr) + " was not a valid MAC address");
}
long longAddr = 0;
for (byte b : addr) {
- longAddr = (longAddr << 8) + BitUtils.uint8(b);
+ final int uint8Byte = b & 255;
+ longAddr = (longAddr << 8) + uint8Byte;
}
return longAddr;
}
diff --git a/staticlibs/src_servicescommon/android/net/NetworkFactory.java b/staticlibs/src_servicescommon/android/net/NetworkFactory.java
new file mode 100644
index 0000000..571f796
--- /dev/null
+++ b/staticlibs/src_servicescommon/android/net/NetworkFactory.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2014 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.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A NetworkFactory is an entity that creates NetworkAgent objects.
+ * The bearers register with ConnectivityService using {@link #register} and
+ * their factory will start receiving scored NetworkRequests. NetworkRequests
+ * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
+ * overridden function. All of these can be dynamic - changing NetworkCapabilities
+ * or score forces re-evaluation of all current requests.
+ *
+ * If any requests pass the filter some overrideable functions will be called.
+ * If the bearer only cares about very simple start/stopNetwork callbacks, those
+ * functions can be overridden. If the bearer needs more interaction, it can
+ * override addNetworkRequest and removeNetworkRequest which will give it each
+ * request that passes their current filters.
+ * @hide
+ **/
+public class NetworkFactory extends Handler {
+ /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
+ public static class SerialNumber {
+ // Guard used by no network factory.
+ public static final int NONE = -1;
+ // A hardcoded serial number for NetworkAgents representing VPNs. These agents are
+ // not created by any factory, so they use this constant for clarity instead of NONE.
+ public static final int VPN = -2;
+ private static final AtomicInteger sNetworkFactorySerialNumber = new AtomicInteger(1);
+ /** Returns a unique serial number for a factory. */
+ public static final int nextSerialNumber() {
+ return sNetworkFactorySerialNumber.getAndIncrement();
+ }
+ }
+
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+ /**
+ * Pass a network request to the bearer. If the bearer believes it can
+ * satisfy the request it should connect to the network and create a
+ * NetworkAgent. Once the NetworkAgent is fully functional it will
+ * register itself with ConnectivityService using registerNetworkAgent.
+ * If the bearer cannot immediately satisfy the request (no network,
+ * user disabled the radio, lower-scored network) it should remember
+ * any NetworkRequests it may be able to satisfy in the future. It may
+ * disregard any that it will never be able to service, for example
+ * those requiring a different bearer.
+ * msg.obj = NetworkRequest
+ * msg.arg1 = score - the score of the network currently satisfying this
+ * request. If this bearer knows in advance it cannot
+ * exceed this score it should not try to connect, holding the request
+ * for the future.
+ * Note that subsequent events may give a different (lower
+ * or higher) score for this request, transmitted to each
+ * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
+ * with the same NetworkRequest but an updated score.
+ * Also, network conditions may change for this bearer
+ * allowing for a better score in the future.
+ * msg.arg2 = the ID of the NetworkProvider currently responsible for the
+ * NetworkAgent handling this request, or NetworkProvider.ID_NONE if none.
+ */
+ public static final int CMD_REQUEST_NETWORK = 1;
+
+ /**
+ * Cancel a network request
+ * msg.obj = NetworkRequest
+ */
+ public static final int CMD_CANCEL_REQUEST = 2;
+
+ /**
+ * Internally used to set our best-guess score.
+ * msg.arg1 = new score
+ */
+ private static final int CMD_SET_SCORE = 3;
+
+ /**
+ * Internally used to set our current filter for coarse bandwidth changes with
+ * technology changes.
+ * msg.obj = new filter
+ */
+ private static final int CMD_SET_FILTER = 4;
+
+ private final Context mContext;
+ private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
+ private final String LOG_TAG;
+
+ private final Map<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
+ new HashMap<>();
+
+ private int mScore;
+ private NetworkCapabilities mCapabilityFilter;
+
+ private int mRefCount = 0;
+ private Messenger mMessenger = null;
+ private NetworkProvider mProvider = null;
+ private int mProviderId;
+
+ public NetworkFactory(Looper looper, Context context, String logTag,
+ NetworkCapabilities filter) {
+ super(looper);
+ LOG_TAG = logTag;
+ mContext = context;
+ mCapabilityFilter = filter;
+ }
+
+ public void register() {
+ if (mProvider != null) {
+ Log.e(LOG_TAG, "Ignoring attempt to register already-registered NetworkFactory");
+ return;
+ }
+ if (DBG) log("Registering NetworkFactory");
+
+ mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
+ @Override
+ public void onNetworkRequested(@NonNull NetworkRequest request, int score,
+ int servingProviderId) {
+ handleAddRequest((NetworkRequest) request, score, servingProviderId);
+ }
+
+ @Override
+ public void onRequestWithdrawn(@NonNull NetworkRequest request) {
+ handleRemoveRequest(request);
+ }
+ };
+
+ mMessenger = new Messenger(this);
+ mProviderId = ((ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);
+ }
+
+ public void unregister() {
+ if (mProvider == null) {
+ Log.e(LOG_TAG, "Ignoring attempt to unregister unregistered NetworkFactory");
+ return;
+ }
+ if (DBG) log("Unregistering NetworkFactory");
+
+ ((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .unregisterNetworkProvider(mProvider);
+ mProvider = null;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_REQUEST_NETWORK: {
+ handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
+ break;
+ }
+ case CMD_CANCEL_REQUEST: {
+ handleRemoveRequest((NetworkRequest) msg.obj);
+ break;
+ }
+ case CMD_SET_SCORE: {
+ handleSetScore(msg.arg1);
+ break;
+ }
+ case CMD_SET_FILTER: {
+ handleSetFilter((NetworkCapabilities) msg.obj);
+ break;
+ }
+ }
+ }
+
+ private class NetworkRequestInfo {
+ public final NetworkRequest request;
+ public int score;
+ public boolean requested; // do we have a request outstanding, limited by score
+ public int providerId;
+
+ NetworkRequestInfo(NetworkRequest request, int score, int providerId) {
+ this.request = request;
+ this.score = score;
+ this.requested = false;
+ this.providerId = providerId;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + request + ", score=" + score + ", requested=" + requested + "}";
+ }
+ }
+
+ /**
+ * Add a NetworkRequest that the bearer may want to attempt to satisfy.
+ * @see #CMD_REQUEST_NETWORK
+ *
+ * @param request the request to handle.
+ * @param score the score of the NetworkAgent currently satisfying this request.
+ */
+ // TODO : remove this method. It is a stopgap measure to help sheperding a number
+ // of dependent changes that would conflict throughout the automerger graph. Having this
+ // temporarily helps with the process of going through with all these dependent changes across
+ // the entire tree.
+ @VisibleForTesting
+ protected void handleAddRequest(NetworkRequest request, int score) {
+ handleAddRequest(request, score, NetworkProvider.ID_NONE);
+ }
+
+ /**
+ * Add a NetworkRequest that the bearer may want to attempt to satisfy.
+ * @see #CMD_REQUEST_NETWORK
+ *
+ * @param request the request to handle.
+ * @param score the score of the NetworkAgent currently satisfying this request.
+ * @param servingProviderId the ID of the NetworkProvider that created the NetworkAgent
+ * currently satisfying this request.
+ */
+ @VisibleForTesting
+ protected void handleAddRequest(NetworkRequest request, int score, int servingProviderId) {
+ NetworkRequestInfo n = mNetworkRequests.get(request);
+ if (n == null) {
+ if (DBG) {
+ log("got request " + request + " with score " + score
+ + " and providerId " + servingProviderId);
+ }
+ n = new NetworkRequestInfo(request, score, servingProviderId);
+ mNetworkRequests.put(n.request, n);
+ } else {
+ if (VDBG) {
+ log("new score " + score + " for existing request " + request
+ + " and providerId " + servingProviderId);
+ }
+ n.score = score;
+ n.providerId = servingProviderId;
+ }
+ if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
+
+ evalRequest(n);
+ }
+
+ @VisibleForTesting
+ protected void handleRemoveRequest(NetworkRequest request) {
+ NetworkRequestInfo n = mNetworkRequests.get(request);
+ if (n != null) {
+ mNetworkRequests.remove(request);
+ if (n.requested) releaseNetworkFor(n.request);
+ }
+ }
+
+ private void handleSetScore(int score) {
+ mScore = score;
+ evalRequests();
+ }
+
+ private void handleSetFilter(NetworkCapabilities netCap) {
+ mCapabilityFilter = netCap;
+ evalRequests();
+ }
+
+ /**
+ * Overridable function to provide complex filtering.
+ * Called for every request every time a new NetworkRequest is seen
+ * and whenever the filterScore or filterNetworkCapabilities change.
+ *
+ * acceptRequest can be overridden to provide complex filter behavior
+ * for the incoming requests
+ *
+ * For output, this class will call {@link #needNetworkFor} and
+ * {@link #releaseNetworkFor} for every request that passes the filters.
+ * If you don't need to see every request, you can leave the base
+ * implementations of those two functions and instead override
+ * {@link #startNetwork} and {@link #stopNetwork}.
+ *
+ * If you want to see every score fluctuation on every request, set
+ * your score filter to a very high number and watch {@link #needNetworkFor}.
+ *
+ * @return {@code true} to accept the request.
+ */
+ public boolean acceptRequest(NetworkRequest request, int score) {
+ return true;
+ }
+
+ private void evalRequest(NetworkRequestInfo n) {
+ if (VDBG) {
+ log("evalRequest");
+ log(" n.requests = " + n.requested);
+ log(" n.score = " + n.score);
+ log(" mScore = " + mScore);
+ log(" n.providerId = " + n.providerId);
+ log(" mProviderId = " + mProviderId);
+ }
+ if (shouldNeedNetworkFor(n)) {
+ if (VDBG) log(" needNetworkFor");
+ needNetworkFor(n.request, n.score);
+ n.requested = true;
+ } else if (shouldReleaseNetworkFor(n)) {
+ if (VDBG) log(" releaseNetworkFor");
+ releaseNetworkFor(n.request);
+ n.requested = false;
+ } else {
+ if (VDBG) log(" done");
+ }
+ }
+
+ private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
+ // If this request is already tracked, it doesn't qualify for need
+ return !n.requested
+ // If the score of this request is higher or equal to that of this factory and some
+ // other factory is responsible for it, then this factory should not track the request
+ // because it has no hope of satisfying it.
+ && (n.score < mScore || n.providerId == mProviderId)
+ // If this factory can't satisfy the capability needs of this request, then it
+ // should not be tracked.
+ && n.request.satisfiedBy(mCapabilityFilter)
+ // Finally if the concrete implementation of the factory rejects the request, then
+ // don't track it.
+ && acceptRequest(n.request, n.score);
+ }
+
+ private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
+ // Don't release a request that's not tracked.
+ return n.requested
+ // The request should be released if it can't be satisfied by this factory. That
+ // means either of the following conditions are met :
+ // - Its score is too high to be satisfied by this factory and it's not already
+ // assigned to the factory
+ // - This factory can't satisfy the capability needs of the request
+ // - The concrete implementation of the factory rejects the request
+ && ((n.score > mScore && n.providerId != mProviderId)
+ || !n.request.satisfiedBy(mCapabilityFilter)
+ || !acceptRequest(n.request, n.score));
+ }
+
+ private void evalRequests() {
+ for (NetworkRequestInfo n : mNetworkRequests.values()) {
+ evalRequest(n);
+ }
+ }
+
+ /**
+ * Post a command, on this NetworkFactory Handler, to re-evaluate all
+ * outstanding requests. Can be called from a factory implementation.
+ */
+ protected void reevaluateAllRequests() {
+ post(() -> {
+ evalRequests();
+ });
+ }
+
+ /**
+ * Can be called by a factory to release a request as unfulfillable: the request will be
+ * removed, and the caller will get a
+ * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
+ * returns.
+ *
+ * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
+ * is able to fulfill this request!
+ */
+ protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
+ post(() -> {
+ if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
+ final NetworkProvider provider = mProvider;
+ if (provider == null) {
+ Log.e(LOG_TAG, "Ignoring attempt to release unregistered request as unfulfillable");
+ return;
+ }
+ provider.declareNetworkRequestUnfulfillable(r);
+ });
+ }
+
+ // override to do simple mode (request independent)
+ protected void startNetwork() { }
+ protected void stopNetwork() { }
+
+ // override to do fancier stuff
+ protected void needNetworkFor(NetworkRequest networkRequest, int score) {
+ if (++mRefCount == 1) startNetwork();
+ }
+
+ protected void releaseNetworkFor(NetworkRequest networkRequest) {
+ if (--mRefCount == 0) stopNetwork();
+ }
+
+ public void setScoreFilter(int score) {
+ sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
+ }
+
+ public void setCapabilityFilter(NetworkCapabilities netCap) {
+ sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
+ }
+
+ @VisibleForTesting
+ protected int getRequestCount() {
+ return mNetworkRequests.size();
+ }
+
+ /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
+ public int getSerialNumber() {
+ return mProviderId;
+ }
+
+ public int getProviderId() {
+ return mProviderId;
+ }
+
+ protected void log(String s) {
+ Log.d(LOG_TAG, s);
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.println(toString());
+ for (NetworkRequestInfo n : mNetworkRequests.values()) {
+ writer.println(" " + n);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mProviderId=")
+ .append(mProviderId).append(", ScoreFilter=")
+ .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
+ .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
+ .append("}");
+ return sb.toString();
+ }
+}