[automerger skipped] Merge "Build module common libs as system_current" am: da0445a3fc am: 85223eb994 am: 7ca5d3fb1a -s ours
am skip reason: Change-Id I2ea2be0039b67ba34fc26e62bdb839ab7d42300c with SHA-1 48d002718f is in history

Change-Id: I010fcd11d39ed6ab3dc152f10835bb2070e76974
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index 1462fd6..8f845bc 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -41,7 +41,6 @@
     jarjar_rules: "jarjar-rules-shared.txt",
     visibility: [
         "//frameworks/base/packages/Tethering",
-        "//frameworks/opt/net/wifi",
         "//frameworks/opt/net/ike",
         "//frameworks/opt/telephony",
         "//packages/modules/NetworkStack",
@@ -58,9 +57,8 @@
     ],
     sdk_version: "system_current",
     visibility: [
-        "//frameworks/base/services",
+        "//frameworks/base/services/net",
         "//frameworks/base/packages/Tethering",
-        "//frameworks/opt/net/wifi/service",
         "//frameworks/opt/net/ike",
         "//packages/modules/NetworkStack",
         "//packages/modules/CaptivePortalLogin",
@@ -80,3 +78,31 @@
         "//frameworks/opt/telephony",
     ],
 }
+
+// Use a filegroup and not a library for wifi sources, as this needs corresponding jar-jar
+// rules on the wifi side.
+// Any class here *must* have a corresponding jarjar rule in the wifi build rules.
+filegroup {
+    name: "net-utils-framework-wifi-common-srcs",
+    srcs: [
+        "src_frameworkcommon/android/net/util/nsd/DnsSdTxtRecord.java",
+        "src_frameworkcommon/android/net/util/MacAddressUtils.java",
+    ],
+    visibility: [
+        "//frameworks/base",
+    ],
+}
+
+// Use a filegroup and not a library for wifi sources, as this needs corresponding jar-jar
+// rules on the wifi side.
+// Any class here *must* have a corresponding jarjar rule in the wifi build rules.
+filegroup {
+    name: "net-utils-wifi-service-common-srcs",
+    srcs: [
+        "src_frameworkcommon/android/net/util/NetUtils.java",
+        "src_servicescommon/android/net/NetworkFactory.java",
+    ],
+    visibility: [
+        "//frameworks/opt/net/wifi/service",
+    ],
+}
diff --git a/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java b/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
index e71f8fb..3ad452b 100644
--- a/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
+++ b/staticlibs/src_frameworkcommon/android/net/util/MacAddressUtils.java
@@ -103,7 +103,7 @@
         }
         long longAddr = 0;
         for (byte b : addr) {
-            final int uint8Byte = b & 255;
+            final int uint8Byte = b & 0xff;
             longAddr = (longAddr << 8) + uint8Byte;
         }
         return longAddr;
diff --git a/staticlibs/src_frameworkcommon/android/net/util/nsd/DnsSdTxtRecord.java b/staticlibs/src_frameworkcommon/android/net/util/nsd/DnsSdTxtRecord.java
new file mode 100644
index 0000000..81768f7
--- /dev/null
+++ b/staticlibs/src_frameworkcommon/android/net/util/nsd/DnsSdTxtRecord.java
@@ -0,0 +1,325 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * 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.
+
+ To do:
+ - implement remove()
+ - fix set() to replace existing values
+ */
+
+package android.net.util.nsd;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.Arrays;
+
+/**
+ * This class handles TXT record data for DNS based service discovery as specified at
+ * http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd-11
+ *
+ * DNS-SD specifies that a TXT record corresponding to an SRV record consist of
+ * a packed array of bytes, each preceded by a length byte. Each string
+ * is an attribute-value pair.
+ *
+ * The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it
+ * as need be to implement its various methods.
+ * @hide
+ *
+ */
+public class DnsSdTxtRecord implements Parcelable {
+    private static final byte mSeparator = '=';
+
+    private byte[] mData;
+
+    /** Constructs a new, empty TXT record. */
+    public DnsSdTxtRecord()  {
+        mData = new byte[0];
+    }
+
+    /** Constructs a new TXT record from a byte array in the standard format. */
+    public DnsSdTxtRecord(byte[] data) {
+        mData = (byte[]) data.clone();
+    }
+
+    /** Copy constructor */
+    public DnsSdTxtRecord(DnsSdTxtRecord src) {
+        if (src != null && src.mData != null) {
+            mData = (byte[]) src.mData.clone();
+        }
+    }
+
+    /**
+     * Set a key/value pair. Setting an existing key will replace its value.
+     * @param key Must be ascii with no '='
+     * @param value matching value to key
+     */
+    public void set(String key, String value) {
+        byte[] keyBytes;
+        byte[] valBytes;
+        int valLen;
+
+        if (value != null) {
+            valBytes = value.getBytes();
+            valLen = valBytes.length;
+        } else {
+            valBytes = null;
+            valLen = 0;
+        }
+
+        try {
+            keyBytes = key.getBytes("US-ASCII");
+        }
+        catch (java.io.UnsupportedEncodingException e) {
+            throw new IllegalArgumentException("key should be US-ASCII");
+        }
+
+        for (int i = 0; i < keyBytes.length; i++) {
+            if (keyBytes[i] == '=') {
+                throw new IllegalArgumentException("= is not a valid character in key");
+            }
+        }
+
+        if (keyBytes.length + valLen >= 255) {
+            throw new IllegalArgumentException("Key and Value length cannot exceed 255 bytes");
+        }
+
+        int currentLoc = remove(key);
+        if (currentLoc == -1)
+            currentLoc = keyCount();
+
+        insert(keyBytes, valBytes, currentLoc);
+    }
+
+    /**
+     * Get a value for a key
+     *
+     * @param key
+     * @return The value associated with the key
+     */
+    public String get(String key) {
+        byte[] val = this.getValue(key);
+        return val != null ? new String(val) : null;
+    }
+
+    /** Remove a key/value pair. If found, returns the index or -1 if not found */
+    public int remove(String key) {
+        int avStart = 0;
+
+        for (int i=0; avStart < mData.length; i++) {
+            int avLen = mData[avStart];
+            if (key.length() <= avLen &&
+                    (key.length() == avLen || mData[avStart + key.length() + 1] == mSeparator)) {
+                String s = new String(mData, avStart + 1, key.length());
+                if (0 == key.compareToIgnoreCase(s)) {
+                    byte[] oldBytes = mData;
+                    mData = new byte[oldBytes.length - avLen - 1];
+                    System.arraycopy(oldBytes, 0, mData, 0, avStart);
+                    System.arraycopy(oldBytes, avStart + avLen + 1, mData, avStart,
+                            oldBytes.length - avStart - avLen - 1);
+                    return i;
+                }
+            }
+            avStart += (0xFF & (avLen + 1));
+        }
+        return -1;
+    }
+
+    /** Return the count of keys */
+    public int keyCount() {
+        int count = 0, nextKey;
+        for (nextKey = 0; nextKey < mData.length; count++) {
+            nextKey += (0xFF & (mData[nextKey] + 1));
+        }
+        return count;
+    }
+
+    /** Return true if key is present, false if not. */
+    public boolean contains(String key) {
+        String s = null;
+        for (int i = 0; null != (s = this.getKey(i)); i++) {
+            if (0 == key.compareToIgnoreCase(s)) return true;
+        }
+        return false;
+    }
+
+    /* Gets the size in bytes */
+    public int size() {
+        return mData.length;
+    }
+
+    /* Gets the raw data in bytes */
+    public byte[] getRawData() {
+        return (byte[]) mData.clone();
+    }
+
+    private void insert(byte[] keyBytes, byte[] value, int index) {
+        byte[] oldBytes = mData;
+        int valLen = (value != null) ? value.length : 0;
+        int insertion = 0;
+        int newLen, avLen;
+
+        for (int i = 0; i < index && insertion < mData.length; i++) {
+            insertion += (0xFF & (mData[insertion] + 1));
+        }
+
+        avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
+        newLen = avLen + oldBytes.length + 1;
+
+        mData = new byte[newLen];
+        System.arraycopy(oldBytes, 0, mData, 0, insertion);
+        int secondHalfLen = oldBytes.length - insertion;
+        System.arraycopy(oldBytes, insertion, mData, newLen - secondHalfLen, secondHalfLen);
+        mData[insertion] = (byte) avLen;
+        System.arraycopy(keyBytes, 0, mData, insertion + 1, keyBytes.length);
+        if (value != null) {
+            mData[insertion + 1 + keyBytes.length] = mSeparator;
+            System.arraycopy(value, 0, mData, insertion + keyBytes.length + 2, valLen);
+        }
+    }
+
+    /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
+    private String getKey(int index) {
+        int avStart = 0;
+
+        for (int i=0; i < index && avStart < mData.length; i++) {
+            avStart += mData[avStart] + 1;
+        }
+
+        if (avStart < mData.length) {
+            int avLen = mData[avStart];
+            int aLen = 0;
+
+            for (aLen=0; aLen < avLen; aLen++) {
+                if (mData[avStart + aLen + 1] == mSeparator) break;
+            }
+            return new String(mData, avStart + 1, aLen);
+        }
+        return null;
+    }
+
+    /**
+     * Look up a key in the TXT record by zero-based index and return its value.
+     * Returns null if index exceeds the total number of keys.
+     * Returns null if the key is present with no value.
+     */
+    private byte[] getValue(int index) {
+        int avStart = 0;
+        byte[] value = null;
+
+        for (int i=0; i < index && avStart < mData.length; i++) {
+            avStart += mData[avStart] + 1;
+        }
+
+        if (avStart < mData.length) {
+            int avLen = mData[avStart];
+            int aLen = 0;
+
+            for (aLen=0; aLen < avLen; aLen++) {
+                if (mData[avStart + aLen + 1] == mSeparator) {
+                    value = new byte[avLen - aLen - 1];
+                    System.arraycopy(mData, avStart + aLen + 2, value, 0, avLen - aLen - 1);
+                    break;
+                }
+            }
+        }
+        return value;
+    }
+
+    private String getValueAsString(int index) {
+        byte[] value = this.getValue(index);
+        return value != null ? new String(value) : null;
+    }
+
+    private byte[] getValue(String forKey) {
+        String s = null;
+        int i;
+
+        for (i = 0; null != (s = this.getKey(i)); i++) {
+            if (0 == forKey.compareToIgnoreCase(s)) {
+                return this.getValue(i);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return a string representation.
+     * Example : {key1=value1},{key2=value2}..
+     *
+     * For a key say like "key3" with null value
+     * {key1=value1},{key2=value2}{key3}
+     */
+    public String toString() {
+        String a, result = null;
+
+        for (int i = 0; null != (a = this.getKey(i)); i++) {
+            String av =  "{" + a;
+            String val = this.getValueAsString(i);
+            if (val != null)
+                av += "=" + val + "}";
+            else
+                av += "}";
+            if (result == null)
+                result = av;
+            else
+                result = result + ", " + av;
+        }
+        return result != null ? result : "";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof DnsSdTxtRecord)) {
+            return false;
+        }
+
+        DnsSdTxtRecord record = (DnsSdTxtRecord)o;
+        return  Arrays.equals(record.mData, mData);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mData);
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByteArray(mData);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final @android.annotation.NonNull Creator<DnsSdTxtRecord> CREATOR =
+        new Creator<DnsSdTxtRecord>() {
+            public DnsSdTxtRecord createFromParcel(Parcel in) {
+                DnsSdTxtRecord info = new DnsSdTxtRecord();
+                in.readByteArray(info.mData);
+                return info;
+            }
+
+            public DnsSdTxtRecord[] newArray(int size) {
+                return new DnsSdTxtRecord[size];
+            }
+        };
+}
diff --git a/staticlibs/src_servicescommon/android/net/NetworkFactory.java b/staticlibs/src_servicescommon/android/net/NetworkFactory.java
index 571f796..47054f5 100644
--- a/staticlibs/src_servicescommon/android/net/NetworkFactory.java
+++ b/staticlibs/src_servicescommon/android/net/NetworkFactory.java
@@ -29,9 +29,8 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * A NetworkFactory is an entity that creates NetworkAgent objects.
@@ -49,20 +48,6 @@
  * @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;
     /**
@@ -115,7 +100,7 @@
     private final String LOG_TAG;
 
     private final Map<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
-            new HashMap<>();
+            new LinkedHashMap<>();
 
     private int mScore;
     private NetworkCapabilities mCapabilityFilter;
@@ -123,7 +108,6 @@
     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) {
@@ -154,7 +138,7 @@
         };
 
         mMessenger = new Messenger(this);
-        mProviderId = ((ConnectivityManager) mContext.getSystemService(
+        ((ConnectivityManager) mContext.getSystemService(
             Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);
     }
 
@@ -307,8 +291,8 @@
             log(" n.requests = " + n.requested);
             log(" n.score = " + n.score);
             log(" mScore = " + mScore);
-            log(" n.providerId = " + n.providerId);
-            log(" mProviderId = " + mProviderId);
+            log(" request.providerId = " + n.providerId);
+            log(" mProvider.id = " + mProvider.getProviderId());
         }
         if (shouldNeedNetworkFor(n)) {
             if (VDBG) log("  needNetworkFor");
@@ -329,7 +313,7 @@
             // 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)
+            && (n.score < mScore || n.providerId == mProvider.getProviderId())
             // If this factory can't satisfy the capability needs of this request, then it
             // should not be tracked.
             && n.request.satisfiedBy(mCapabilityFilter)
@@ -347,7 +331,7 @@
             //   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.score > mScore && n.providerId != mProvider.getProviderId())
                     || !n.request.satisfiedBy(mCapabilityFilter)
                     || !acceptRequest(n.request, n.score));
     }
@@ -417,11 +401,11 @@
 
     /* TODO: delete when all callers have migrated to NetworkProvider IDs. */
     public int getSerialNumber() {
-        return mProviderId;
+        return mProvider.getProviderId();
     }
 
-    public int getProviderId() {
-        return mProviderId;
+    public NetworkProvider getProvider() {
+        return mProvider;
     }
 
     protected void log(String s) {
@@ -437,8 +421,8 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mProviderId=")
-                .append(mProviderId).append(", ScoreFilter=")
+        StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - providerId=")
+                .append(mProvider.getProviderId()).append(", ScoreFilter=")
                 .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
                 .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
                 .append("}");