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();
+    }
+}