Merge "Add an API hint for metered multipath traffic."
diff --git a/api/current.txt b/api/current.txt
index 740543c..1a6ae5c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -67546,6 +67546,7 @@
   public abstract class SSLSocketFactory extends javax.net.SocketFactory {
     ctor public SSLSocketFactory();
     method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.Socket, java.io.InputStream, boolean) throws java.io.IOException;
     method public static synchronized javax.net.SocketFactory getDefault();
     method public abstract java.lang.String[] getDefaultCipherSuites();
     method public abstract java.lang.String[] getSupportedCipherSuites();
diff --git a/api/system-current.txt b/api/system-current.txt
index 239ac70..12a0b0e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -71172,6 +71172,7 @@
   public abstract class SSLSocketFactory extends javax.net.SocketFactory {
     ctor public SSLSocketFactory();
     method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.Socket, java.io.InputStream, boolean) throws java.io.IOException;
     method public static synchronized javax.net.SocketFactory getDefault();
     method public abstract java.lang.String[] getDefaultCipherSuites();
     method public abstract java.lang.String[] getSupportedCipherSuites();
diff --git a/api/test-current.txt b/api/test-current.txt
index 8108a4b..a0362b4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -67655,6 +67655,7 @@
   public abstract class SSLSocketFactory extends javax.net.SocketFactory {
     ctor public SSLSocketFactory();
     method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException;
+    method public java.net.Socket createSocket(java.net.Socket, java.io.InputStream, boolean) throws java.io.IOException;
     method public static synchronized javax.net.SocketFactory getDefault();
     method public abstract java.lang.String[] getDefaultCipherSuites();
     method public abstract java.lang.String[] getSupportedCipherSuites();
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index 7e37157..4e9fac3 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -241,8 +241,8 @@
      */
     public static final class Builder {
 
-        private boolean connectable = true;
-        private boolean scannable = true;
+        private boolean connectable = false;
+        private boolean scannable = false;
         private boolean isLegacy = false;
         private boolean isAnonymous = false;
         private boolean includeTxPower = false;
@@ -254,10 +254,10 @@
         /**
          * Set whether the advertisement type should be connectable or
          * non-connectable.
-         * Legacy advertisements must be both connectable and scannable. Nonlegacy
+         * Legacy advertisements can be both connectable and scannable. Non-legacy
          * advertisements can be only scannable or only connectable.
          * @param connectable Controls whether the advertisment type will be
-         * connectable (true) or nonconnectable (false).
+         * connectable (true) or non-connectable (false).
          */
         public Builder setConnectable(boolean connectable) {
             this.connectable = connectable;
@@ -266,10 +266,10 @@
 
         /**
          * Set whether the advertisement type should be scannable.
-         * Legacy advertisements must be both connectable and scannable. Nonlegacy
+         * Legacy advertisements can be both connectable and scannable. Non-legacy
          * advertisements can be only scannable or only connectable.
          * @param scannable Controls whether the advertisment type will be
-         * scannable (true) or nonscannable (false).
+         * scannable (true) or non-scannable (false).
          */
         public Builder setScannable(boolean scannable) {
             this.scannable = scannable;
diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java
index 9326203..3617aa7 100644
--- a/core/java/android/util/IntArray.java
+++ b/core/java/android/util/IntArray.java
@@ -17,7 +17,7 @@
 package android.util;
 
 import com.android.internal.util.ArrayUtils;
-
+import com.android.internal.util.Preconditions;
 import java.util.Arrays;
 import libcore.util.EmptyArray;
 
@@ -32,6 +32,11 @@
     private int[] mValues;
     private int mSize;
 
+    private  IntArray(int[] array, int size) {
+        mValues = array;
+        mSize = Preconditions.checkArgumentInRange(size, 0, array.length, "size");
+    }
+
     /**
      * Creates an empty IntArray with the default initial capacity.
      */
@@ -52,6 +57,35 @@
     }
 
     /**
+     * Creates an IntArray wrapping the given primitive int array.
+     */
+    public static IntArray wrap(int[] array) {
+        return new IntArray(array, array.length);
+    }
+
+    /**
+     * Creates an IntArray from the given primitive int array, copying it.
+     */
+    public static IntArray fromArray(int[] array, int size) {
+        return wrap(Arrays.copyOf(array, size));
+    }
+
+    /**
+     * Changes the size of this IntArray. If this IntArray is shrinked, the backing array capacity
+     * is unchanged. If the new size is larger than backing array capacity, a new backing array is
+     * created from the current content of this IntArray padded with 0s.
+     */
+    public void resize(int newSize) {
+        Preconditions.checkArgumentNonnegative(newSize);
+        if (newSize <= mValues.length) {
+            Arrays.fill(mValues, newSize, mValues.length, 0);
+        } else {
+            ensureCapacity(newSize - mSize);
+        }
+        mSize = newSize;
+    }
+
+    /**
      * Appends the specified value to the end of this array.
      */
     public void add(int value) {
@@ -59,23 +93,23 @@
     }
 
     /**
-     * Inserts a value at the specified position in this array.
+     * Inserts a value at the specified position in this array. If the specified index is equal to
+     * the length of the array, the value is added at the end.
      *
      * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt; size()
      */
     public void add(int index, int value) {
-        if (index < 0 || index > mSize) {
-            throw new IndexOutOfBoundsException();
-        }
-
         ensureCapacity(1);
+        int rightSegment = mSize - index;
+        mSize++;
+        checkBounds(index);
 
-        if (mSize - index != 0) {
-            System.arraycopy(mValues, index, mValues, index + 1, mSize - index);
+        if (rightSegment != 0) {
+            // Move by 1 all values from the right of 'index'
+            System.arraycopy(mValues, index, mValues, index + 1, rightSegment);
         }
 
         mValues[index] = value;
-        mSize++;
     }
 
     /**
@@ -141,13 +175,19 @@
      * Returns the value at the specified position in this array.
      */
     public int get(int index) {
-        if (index >= mSize) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
+        checkBounds(index);
         return mValues[index];
     }
 
     /**
+     * Sets the value at the specified position in this array.
+     */
+    public void set(int index, int value) {
+        checkBounds(index);
+        mValues[index] = value;
+    }
+
+    /**
      * Returns the index of the first occurrence of the specified value in this
      * array, or -1 if this array does not contain the value.
      */
@@ -165,9 +205,7 @@
      * Removes the value at the specified index from this array.
      */
     public void remove(int index) {
-        if (index >= mSize) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
+        checkBounds(index);
         System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
         mSize--;
     }
@@ -185,4 +223,10 @@
     public int[] toArray() {
         return Arrays.copyOf(mValues, mSize);
     }
+
+    private void checkBounds(int index) {
+        if (index < 0 || mSize <= index) {
+            throw new ArrayIndexOutOfBoundsException(mSize, index);
+        }
+    }
 }
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index 54a6882..9b0489c 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,6 +17,8 @@
 package android.util;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
+import java.util.Arrays;
 import libcore.util.EmptyArray;
 
 /**
@@ -30,6 +32,11 @@
     private long[] mValues;
     private int mSize;
 
+    private  LongArray(long[] array, int size) {
+        mValues = array;
+        mSize = Preconditions.checkArgumentInRange(size, 0, array.length, "size");
+    }
+
     /**
      * Creates an empty LongArray with the default initial capacity.
      */
@@ -50,6 +57,35 @@
     }
 
     /**
+     * Creates an LongArray wrapping the given primitive long array.
+     */
+    public static LongArray wrap(long[] array) {
+        return new LongArray(array, array.length);
+    }
+
+    /**
+     * Creates an LongArray from the given primitive long array, copying it.
+     */
+    public static LongArray fromArray(long[] array, int size) {
+        return wrap(Arrays.copyOf(array, size));
+    }
+
+    /**
+     * Changes the size of this LongArray. If this LongArray is shrinked, the backing array capacity
+     * is unchanged. If the new size is larger than backing array capacity, a new backing array is
+     * created from the current content of this LongArray padded with 0s.
+     */
+    public void resize(int newSize) {
+        Preconditions.checkArgumentNonnegative(newSize);
+        if (newSize <= mValues.length) {
+            Arrays.fill(mValues, newSize, mValues.length, 0);
+        } else {
+            ensureCapacity(newSize - mSize);
+        }
+        mSize = newSize;
+    }
+
+    /**
      * Appends the specified value to the end of this array.
      */
     public void add(long value) {
@@ -57,23 +93,23 @@
     }
 
     /**
-     * Inserts a value at the specified position in this array.
+     * Inserts a value at the specified position in this array. If the specified index is equal to
+     * the length of the array, the value is added at the end.
      *
      * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt; size()
      */
     public void add(int index, long value) {
-        if (index < 0 || index > mSize) {
-            throw new IndexOutOfBoundsException();
-        }
-
         ensureCapacity(1);
+        int rightSegment = mSize - index;
+        mSize++;
+        checkBounds(index);
 
-        if (mSize - index != 0) {
-            System.arraycopy(mValues, index, mValues, index + 1, mSize - index);
+        if (rightSegment != 0) {
+            // Move by 1 all values from the right of 'index'
+            System.arraycopy(mValues, index, mValues, index + 1, rightSegment);
         }
 
         mValues[index] = value;
-        mSize++;
     }
 
     /**
@@ -126,13 +162,19 @@
      * Returns the value at the specified position in this array.
      */
     public long get(int index) {
-        if (index >= mSize) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
+        checkBounds(index);
         return mValues[index];
     }
 
     /**
+     * Sets the value at the specified position in this array.
+     */
+    public void set(int index, long value) {
+        checkBounds(index);
+        mValues[index] = value;
+    }
+
+    /**
      * Returns the index of the first occurrence of the specified value in this
      * array, or -1 if this array does not contain the value.
      */
@@ -150,9 +192,7 @@
      * Removes the value at the specified index from this array.
      */
     public void remove(int index) {
-        if (index >= mSize) {
-            throw new ArrayIndexOutOfBoundsException(mSize, index);
-        }
+        checkBounds(index);
         System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
         mSize--;
     }
@@ -163,4 +203,17 @@
     public int size() {
         return mSize;
     }
+
+    /**
+     * Returns a new array with the contents of this LongArray.
+     */
+    public long[] toArray() {
+        return Arrays.copyOf(mValues, mSize);
+    }
+
+    private void checkBounds(int index) {
+        if (index < 0 || mSize <= index) {
+            throw new ArrayIndexOutOfBoundsException(mSize, index);
+        }
+    }
 }
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index c3978e7..577cd49 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -276,7 +276,8 @@
         jstring ifaceNameObj,
         jstring serviceNameObj) {
 
-    using ::android::vintf::operator<<;
+    using ::android::hidl::base::V1_0::IBase;
+    using ::android::hidl::manager::V1_0::IServiceManager;
 
     if (ifaceNameObj == NULL) {
         jniThrowException(env, "java/lang/NullPointerException", NULL);
@@ -318,13 +319,20 @@
               << "/"
               << serviceName;
 
-    ::android::vintf::Transport transport =
-            ::android::hardware::getTransport(ifaceName, serviceName);
-    if (   transport != ::android::vintf::Transport::EMPTY
-        && transport != ::android::vintf::Transport::HWBINDER) {
+    Return<IServiceManager::Transport> transportRet =
+            manager->getTransport(ifaceNameHStr, serviceNameHStr);
+
+    if (!transportRet.isOk()) {
+        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
+        return NULL;
+    }
+
+    IServiceManager::Transport transport = transportRet;
+
+    if (   transport != IServiceManager::Transport::EMPTY
+        && transport != IServiceManager::Transport::HWBINDER) {
         LOG(ERROR) << "service " << ifaceName << " declares transport method "
-                   << transport << " but framework expects "
-                   << ::android::vintf::Transport::HWBINDER;
+                   << toString(transport) << " but framework expects hwbinder.";
         signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
         return NULL;
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 460d466..9991a20 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1257,6 +1257,13 @@
     <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
         android:protectionLevel="signature" />
 
+    <!-- Allows network stack services (Connectivity and Wifi) to coordinate
+         <p>Not for use by third-party or privileged applications.
+         @hide This should only be used by Connectivity and Wifi Services.
+    -->
+    <permission android:name="android.permission.NETWORK_STACK"
+        android:protectionLevel="signature" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
diff --git a/core/tests/utiltests/src/android/util/IntArrayTest.java b/core/tests/utiltests/src/android/util/IntArrayTest.java
new file mode 100644
index 0000000..a6120a1
--- /dev/null
+++ b/core/tests/utiltests/src/android/util/IntArrayTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IntArrayTest {
+
+    @Test
+    public void testIntArray() {
+        IntArray a = new IntArray();
+        a.add(1);
+        a.add(2);
+        a.add(3);
+        verify(new int[]{1, 2, 3}, a);
+
+        IntArray b = IntArray.fromArray(new int[]{4, 5, 6, 7, 8}, 3);
+        a.addAll(b);
+        verify(new int[]{1, 2, 3, 4, 5, 6}, a);
+
+        a.resize(2);
+        verify(new int[]{1, 2}, a);
+
+        a.resize(8);
+        verify(new int[]{1, 2, 0, 0, 0, 0, 0, 0}, a);
+
+        a.set(5, 10);
+        verify(new int[]{1, 2, 0, 0, 0, 10, 0, 0}, a);
+
+        a.add(5, 20);
+        assertEquals(20, a.get(5));
+        assertEquals(5, a.indexOf(20));
+        verify(new int[]{1, 2, 0, 0, 0, 20, 10, 0, 0}, a);
+
+        assertEquals(-1, a.indexOf(99));
+
+        a.resize(15);
+        a.set(14, 30);
+        verify(new int[]{1, 2, 0, 0, 0, 20, 10, 0, 0, 0, 0, 0, 0, 0, 30}, a);
+
+        int[] backingArray = new int[]{1, 2, 3, 4};
+        a = IntArray.wrap(backingArray);
+        a.set(0, 10);
+        assertEquals(10, backingArray[0]);
+        backingArray[1] = 20;
+        backingArray[2] = 30;
+        verify(backingArray, a);
+        assertEquals(2, a.indexOf(30));
+
+        a.resize(2);
+        assertEquals(0, backingArray[2]);
+        assertEquals(0, backingArray[3]);
+
+        a.add(50);
+        verify(new int[]{10, 20, 50}, a);
+    }
+
+    public void verify(int[] expected, IntArray intArray) {
+        assertEquals(expected.length, intArray.size());
+        assertArrayEquals(expected, intArray.toArray());
+    }
+}
diff --git a/core/tests/utiltests/src/android/util/LongArrayTest.java b/core/tests/utiltests/src/android/util/LongArrayTest.java
new file mode 100644
index 0000000..a7afcbd
--- /dev/null
+++ b/core/tests/utiltests/src/android/util/LongArrayTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LongArrayTest {
+
+    @Test
+    public void testLongArray() {
+        LongArray a = new LongArray();
+        a.add(1);
+        a.add(2);
+        a.add(3);
+        verify(new long[]{1, 2, 3}, a);
+
+        LongArray b = LongArray.fromArray(new long[]{4, 5, 6, 7, 8}, 3);
+        a.addAll(b);
+        verify(new long[]{1, 2, 3, 4, 5, 6}, a);
+
+        a.resize(2);
+        verify(new long[]{1, 2}, a);
+
+        a.resize(8);
+        verify(new long[]{1, 2, 0, 0, 0, 0, 0, 0}, a);
+
+        a.set(5, 10);
+        verify(new long[]{1, 2, 0, 0, 0, 10, 0, 0}, a);
+
+        a.add(5, 20);
+        assertEquals(20, a.get(5));
+        assertEquals(5, a.indexOf(20));
+        verify(new long[]{1, 2, 0, 0, 0, 20, 10, 0, 0}, a);
+
+        assertEquals(-1, a.indexOf(99));
+
+        a.resize(15);
+        a.set(14, 30);
+        verify(new long[]{1, 2, 0, 0, 0, 20, 10, 0, 0, 0, 0, 0, 0, 0, 30}, a);
+
+        long[] backingArray = new long[]{1, 2, 3, 4};
+        a = LongArray.wrap(backingArray);
+        a.set(0, 10);
+        assertEquals(10, backingArray[0]);
+        backingArray[1] = 20;
+        backingArray[2] = 30;
+        verify(backingArray, a);
+        assertEquals(2, a.indexOf(30));
+
+        a.resize(2);
+        assertEquals(0, backingArray[2]);
+        assertEquals(0, backingArray[3]);
+
+        a.add(50);
+        verify(new long[]{10, 20, 50}, a);
+    }
+
+    public void verify(long[] expected, LongArray longArrays) {
+        assertEquals(expected.length, longArrays.size());
+        assertArrayEquals(expected, longArrays.toArray());
+    }
+}
diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
index b6c45b7..2bab1b6 100644
--- a/packages/PrintRecommendationService/res/values/strings.xml
+++ b/packages/PrintRecommendationService/res/values/strings.xml
@@ -18,6 +18,7 @@
 -->
 
 <resources>
+    <string name="plugin_vendor_google_cloud_print">Cloud Print</string>
     <string name="plugin_vendor_hp">HP</string>
     <string name="plugin_vendor_lexmark">Lexmark</string>
     <string name="plugin_vendor_brother">Brother</string>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
index 1fe5a2a..8edd0ec 100644
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java
@@ -21,6 +21,8 @@
 import android.printservice.recommendation.RecommendationService;
 import android.printservice.PrintService;
 import android.util.Log;
+
+import com.android.printservice.recommendation.plugin.google.CloudPrintPlugin;
 import com.android.printservice.recommendation.plugin.hp.HPRecommendationPlugin;
 import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin;
 import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig;
@@ -61,6 +63,14 @@
         }
 
         try {
+            mPlugins.add(new RemotePrintServicePlugin(new CloudPrintPlugin(this), this,
+                    true));
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Could not initiate "
+                            + getString(R.string.plugin_vendor_google_cloud_print) + " plugin", e);
+        }
+
+        try {
             mPlugins.add(new RemotePrintServicePlugin(new HPRecommendationPlugin(this), this,
                     false));
         } catch (Exception e) {
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
new file mode 100644
index 0000000..05b0c86
--- /dev/null
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 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.printservice.recommendation.plugin.google;
+
+import static com.android.printservice.recommendation.util.MDNSUtils.ATTRIBUTE_TY;
+
+import android.annotation.NonNull;
+import android.annotation.StringRes;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.printservice.recommendation.PrintServicePlugin;
+import com.android.printservice.recommendation.R;
+import com.android.printservice.recommendation.util.MDNSFilteredDiscovery;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Plugin detecting <a href="https://developers.google.com/cloud-print/docs/privet">Google Cloud
+ * Print</a> printers.
+ */
+public class CloudPrintPlugin implements PrintServicePlugin {
+    private static final String LOG_TAG = CloudPrintPlugin.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private static final String ATTRIBUTE_TXTVERS = "txtvers";
+    private static final String ATTRIBUTE_URL = "url";
+    private static final String ATTRIBUTE_TYPE = "type";
+    private static final String ATTRIBUTE_ID = "id";
+    private static final String ATTRIBUTE_CS = "cs";
+
+    private static final String TYPE = "printer";
+
+    private static final String PRIVET_SERVICE = "_privet._tcp";
+
+    /** The required mDNS service types */
+    private static final Set<String> PRINTER_SERVICE_TYPE = new HashSet<String>() {{
+        // Not checking _printer_._sub
+        add(PRIVET_SERVICE);
+    }};
+
+    /** All possible connection states */
+    private static final Set<String> POSSIBLE_CONNECTION_STATES = new HashSet<String>() {{
+        add("online");
+        add("offline");
+        add("connecting");
+        add("not-configured");
+    }};
+
+    private static final byte SUPPORTED_TXTVERS = '1';
+
+    /** The mDNS filtered discovery */
+    private final MDNSFilteredDiscovery mMDNSFilteredDiscovery;
+
+    /**
+     * Create a plugin detecting Google Cloud Print printers.
+     *
+     * @param context The context the plugin runs in
+     */
+    public CloudPrintPlugin(@NonNull Context context) {
+        mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPE,
+                nsdServiceInfo -> {
+                    // The attributes are case insensitive. For faster searching create a clone of
+                    // the map with the attribute-keys all in lower case.
+                    ArrayMap<String, byte[]> caseInsensitiveAttributes =
+                            new ArrayMap<>(nsdServiceInfo.getAttributes().size());
+                    for (Map.Entry<String, byte[]> entry : nsdServiceInfo.getAttributes()
+                            .entrySet()) {
+                        caseInsensitiveAttributes.put(entry.getKey().toLowerCase(),
+                                entry.getValue());
+                    }
+
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, nsdServiceInfo.getServiceName() + ":");
+                        Log.i(LOG_TAG, "type:  " + nsdServiceInfo.getServiceType());
+                        Log.i(LOG_TAG, "host:  " + nsdServiceInfo.getHost());
+                        for (Map.Entry<String, byte[]> entry : caseInsensitiveAttributes.entrySet()) {
+                            if (entry.getValue() == null) {
+                                Log.i(LOG_TAG, entry.getKey() + "= null");
+                            } else {
+                                Log.i(LOG_TAG, entry.getKey() + "=" + new String(entry.getValue(),
+                                        StandardCharsets.UTF_8));
+                            }
+                        }
+                    }
+
+                    byte[] txtvers = caseInsensitiveAttributes.get(ATTRIBUTE_TXTVERS);
+                    if (txtvers == null || txtvers.length != 1 || txtvers[0] != SUPPORTED_TXTVERS) {
+                        // The spec requires this to be the first attribute, but at this time we
+                        // lost the order of the attributes
+                        return false;
+                    }
+
+                    if (caseInsensitiveAttributes.get(ATTRIBUTE_TY) == null) {
+                        return false;
+                    }
+
+                    byte[] url = caseInsensitiveAttributes.get(ATTRIBUTE_URL);
+                    if (url == null || url.length == 0) {
+                        return false;
+                    }
+
+                    byte[] type = caseInsensitiveAttributes.get(ATTRIBUTE_TYPE);
+                    if (type == null || !TYPE.equals(
+                            new String(type, StandardCharsets.UTF_8).toLowerCase())) {
+                        return false;
+                    }
+
+                    if (caseInsensitiveAttributes.get(ATTRIBUTE_ID) == null) {
+                        return false;
+                    }
+
+                    byte[] cs = caseInsensitiveAttributes.get(ATTRIBUTE_CS);
+                    if (cs == null || !POSSIBLE_CONNECTION_STATES.contains(
+                            new String(cs, StandardCharsets.UTF_8).toLowerCase())) {
+                        return false;
+                    }
+
+                    InetAddress address = nsdServiceInfo.getHost();
+                    if (!(address instanceof Inet4Address)) {
+                        // Not checking for link local address
+                        return false;
+                    }
+
+                    return true;
+                });
+    }
+
+    @Override
+    @NonNull public CharSequence getPackageName() {
+        return "com.google.android.apps.cloudprint";
+    }
+
+    @Override
+    public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception {
+        mMDNSFilteredDiscovery.start(callback);
+    }
+
+    @Override
+    @StringRes public int getName() {
+        return R.string.plugin_vendor_google_cloud_print;
+    }
+
+    @Override
+    public void stop() throws Exception {
+        mMDNSFilteredDiscovery.stop();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
index 26e8303..d1f4dc4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
@@ -139,7 +139,16 @@
             if (preferLongName) {
                 displayName = getZoneLongName(timeZoneNames, tz, now);
             } else {
-                displayName = timeZoneNames.getExemplarLocationName(tz.getID());
+                // Canonicalize the zone ID for ICU. It will only return valid strings for zone IDs
+                // that match ICUs zone IDs (which are similar but not guaranteed the same as those
+                // in timezones.xml). timezones.xml and related files uses the IANA IDs. ICU IDs are
+                // stable and IANA IDs have changed over time so they have drifted.
+                // See http://bugs.icu-project.org/trac/ticket/13070 / http://b/36469833.
+                String canonicalZoneId = android.icu.util.TimeZone.getCanonicalID(tz.getID());
+                if (canonicalZoneId == null) {
+                    canonicalZoneId = tz.getID();
+                }
+                displayName = timeZoneNames.getExemplarLocationName(canonicalZoneId);
                 if (displayName == null || displayName.isEmpty()) {
                     // getZoneExemplarLocation can return null. Fall back to the long name.
                     displayName = getZoneLongName(timeZoneNames, tz, now);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8223cdf..9dde3e2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1303,13 +1303,16 @@
     @Override
     public LinkProperties getLinkProperties(Network network) {
         enforceAccessPermission();
-        NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
-        if (nai != null) {
-            synchronized (nai) {
-                return new LinkProperties(nai.linkProperties);
-            }
+        return getLinkProperties(getNetworkAgentInfoForNetwork(network));
+    }
+
+    private LinkProperties getLinkProperties(NetworkAgentInfo nai) {
+        if (nai == null) {
+            return null;
         }
-        return null;
+        synchronized (nai) {
+            return new LinkProperties(nai.linkProperties);
+        }
     }
 
     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
@@ -3145,7 +3148,8 @@
         enforceAccessPermission();
         enforceInternetPermission();
 
-        NetworkAgentInfo nai;
+        // TODO: execute this logic on ConnectivityService handler.
+        final NetworkAgentInfo nai;
         if (network == null) {
             nai = getDefaultNetwork();
         } else {
@@ -3156,21 +3160,24 @@
             return;
         }
         // Revalidate if the app report does not match our current validated state.
-        if (hasConnectivity == nai.lastValidated) return;
+        if (hasConnectivity == nai.lastValidated) {
+            return;
+        }
         final int uid = Binder.getCallingUid();
         if (DBG) {
             log("reportNetworkConnectivity(" + nai.network.netId + ", " + hasConnectivity +
                     ") by " + uid);
         }
-        synchronized (nai) {
-            // Validating a network that has not yet connected could result in a call to
-            // rematchNetworkAndRequests() which is not meant to work on such networks.
-            if (!nai.everConnected) return;
-
-            if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, false)) return;
-
-            nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
+        // Validating a network that has not yet connected could result in a call to
+        // rematchNetworkAndRequests() which is not meant to work on such networks.
+        if (!nai.everConnected) {
+            return;
         }
+        LinkProperties lp = getLinkProperties(nai);
+        if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
+            return;
+        }
+        nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
     }
 
     private ProxyInfo getDefaultProxy() {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 97669d2..6cf8f37 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -301,6 +301,11 @@
         if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s);
     }
 
+    private void validationLog(int probeType, Object url, String msg) {
+        String probeName = ValidationProbeEvent.getProbeName(probeType);
+        validationLog(String.format("%s %s %s", probeName, url, msg));
+    }
+
     private void validationLog(String s) {
         if (DBG) log(s);
         validationLogs.log(s);
@@ -752,20 +757,19 @@
         String connectInfo;
         try {
             InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host);
-            result = ValidationProbeEvent.DNS_SUCCESS;
-            StringBuffer buffer = new StringBuffer(host).append("=");
+            StringBuffer buffer = new StringBuffer();
             for (InetAddress address : addresses) {
-                buffer.append(address.getHostAddress());
-                if (address != addresses[addresses.length-1]) buffer.append(",");
+                buffer.append(',').append(address.getHostAddress());
             }
-            connectInfo = buffer.toString();
+            result = ValidationProbeEvent.DNS_SUCCESS;
+            connectInfo = "OK " + buffer.substring(1);
         } catch (UnknownHostException e) {
             result = ValidationProbeEvent.DNS_FAILURE;
-            connectInfo = host;
+            connectInfo = "FAIL";
         }
         final long latency = watch.stop();
-        String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL";
-        validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo));
+        validationLog(ValidationProbeEvent.PROBE_DNS, host,
+                String.format("%dms %s", latency, connectInfo));
         logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result);
     }
 
@@ -787,7 +791,7 @@
             urlConnection.setUseCaches(false);
             final String userAgent = getCaptivePortalUserAgent(mContext);
             if (userAgent != null) {
-               urlConnection.setRequestProperty("User-Agent", userAgent);
+                urlConnection.setRequestProperty("User-Agent", userAgent);
             }
             // cannot read request header after connection
             String requestHeader = urlConnection.getRequestProperties().toString();
@@ -801,8 +805,7 @@
             // Time how long it takes to get a response to our request
             long responseTimestamp = SystemClock.elapsedRealtime();
 
-            validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url +
-                    " time=" + (responseTimestamp - requestTimestamp) + "ms" +
+            validationLog(probeType, url, "time=" + (responseTimestamp - requestTimestamp) + "ms" +
                     " ret=" + httpResponseCode +
                     " request=" + requestHeader +
                     " headers=" + urlConnection.getHeaderFields());
@@ -814,27 +817,29 @@
             // proxy server.
             if (httpResponseCode == 200) {
                 if (probeType == ValidationProbeEvent.PROBE_PAC) {
-                    validationLog("PAC fetch 200 response interpreted as 204 response.");
+                    validationLog(
+                            probeType, url, "PAC fetch 200 response interpreted as 204 response.");
                     httpResponseCode = 204;
                 } else if (urlConnection.getContentLengthLong() == 0) {
                     // Consider 200 response with "Content-length=0" to not be a captive portal.
                     // There's no point in considering this a captive portal as the user cannot
                     // sign-in to an empty page. Probably the result of a broken transparent proxy.
                     // See http://b/9972012.
-                    validationLog(
+                    validationLog(probeType, url,
                         "200 response with Content-length=0 interpreted as 204 response.");
                     httpResponseCode = 204;
                 } else if (urlConnection.getContentLengthLong() == -1) {
                     // When no Content-length (default value == -1), attempt to read a byte from the
                     // response. Do not use available() as it is unreliable. See http://b/33498325.
                     if (urlConnection.getInputStream().read() == -1) {
-                        validationLog("Empty 200 response interpreted as 204 response.");
+                        validationLog(
+                                probeType, url, "Empty 200 response interpreted as 204 response.");
                         httpResponseCode = 204;
                     }
                 }
             }
         } catch (IOException e) {
-            validationLog("Probably not a portal: exception " + e);
+            validationLog(probeType, url, "Probably not a portal: exception " + e);
             if (httpResponseCode == 599) {
                 // TODO: Ping gateway and DNS server and log results.
             }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8800f8e..7e0fbb9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -721,6 +721,16 @@
     public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
 
     /**
+     * String array for package names that need to be enabled for this carrier.
+     * If user has explicitly disabled some packages in the list, won't re-enable.
+     * Other carrier specific apps which are not in this list may be disabled for current carrier,
+     * and only be re-enabled when this config for another carrier includes it.
+     *
+     * @hide
+     */
+    public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array";
+
+    /**
      * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference.
      * Some operators support Wi-Fi Calling only, not VoLTE.
      * They don't need "Cellular preferred" option.
@@ -1387,6 +1397,7 @@
         sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false);
         sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL, false);
+        sDefaults.putStringArray(KEY_ENABLE_APPS_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true);
         sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
         sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 011e505..8c16dbb 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -58,8 +58,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -72,6 +70,8 @@
                 "    transport_types: 2",
                 "    transport_types: 3",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -89,13 +89,14 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
+                "    error_code: 0",
                 "    if_name: \"wlan0\"",
                 "    state_transition: \"SomeState\"",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -112,13 +113,14 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  dhcp_event <",
                 "    duration_ms: 0",
-                "    if_name: \"wlan0\"",
                 "    error_code: 50397184",
+                "    if_name: \"wlan0\"",
+                "    state_transition: \"\"",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -137,8 +139,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  dns_lookup_batch <",
                 "    event_types: 1",
                 "    event_types: 1",
@@ -168,6 +168,8 @@
                 "    return_codes: 200",
                 "    return_codes: 178",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -185,13 +187,13 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
                 "    latency_ms: 5678",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -208,12 +210,12 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -231,8 +233,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  network_event <",
                 "    event_type: 5",
                 "    latency_ms: 20410",
@@ -240,6 +240,8 @@
                 "      network_id: 100",
                 "    >",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -287,8 +289,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  apf_program_event <",
                 "    current_ras: 9",
                 "    drop_multicast: true",
@@ -297,6 +297,8 @@
                 "    lifetime: 200",
                 "    program_length: 2048",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -319,8 +321,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -331,6 +331,8 @@
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
@@ -351,8 +353,6 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 1",
-                "  transport: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
@@ -361,6 +361,8 @@
                 "    route_info_lifetime: -1",
                 "    router_lifetime: 2000",
                 "  >",
+                "  time_ms: 1",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 450653c..9a33cde 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -158,25 +158,24 @@
         String want = joinLines(
                 "dropped_events: 0",
                 "events <",
-                "  time_ms: 100",
-                "  transport: 0",
                 "  ip_reachability_event <",
                 "    event_type: 512",
                 "    if_name: \"wlan0\"",
                 "  >",
+                "  time_ms: 100",
+                "  transport: 0",
                 ">",
                 "events <",
-                "  time_ms: 200",
-                "  transport: 0",
                 "  dhcp_event <",
                 "    duration_ms: 192",
+                "    error_code: 0",
                 "    if_name: \"wlan0\"",
                 "    state_transition: \"SomeState\"",
                 "  >",
+                "  time_ms: 200",
+                "  transport: 0",
                 ">",
                 "events <",
-                "  time_ms: 300",
-                "  transport: 0",
                 "  default_network_event <",
                 "    network_id <",
                 "      network_id: 102",
@@ -189,15 +188,17 @@
                 "    transport_types: 2",
                 "    transport_types: 3",
                 "  >",
+                "  time_ms: 300",
+                "  transport: 0",
                 ">",
                 "events <",
-                "  time_ms: 400",
-                "  transport: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"wlan0\"",
                 "    latency_ms: 5678",
                 "  >",
+                "  time_ms: 400",
+                "  transport: 0",
                 ">",
                 "events <",
                 "  time_ms: 500",
@@ -212,8 +213,6 @@
                 "  >",
                 ">",
                 "events <",
-                "  time_ms: 600",
-                "  transport: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
                 "    duration_ms: 45000",
@@ -224,10 +223,10 @@
                 "    received_ras: 10",
                 "    zero_lifetime_ras: 1",
                 "  >",
+                "  time_ms: 600",
+                "  transport: 0",
                 ">",
                 "events <",
-                "  time_ms: 700",
-                "  transport: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
                 "    prefix_preferred_lifetime: 300",
@@ -236,6 +235,8 @@
                 "    route_info_lifetime: -1",
                 "    router_lifetime: 2000",
                 "  >",
+                "  time_ms: 700",
+                "  transport: 0",
                 ">",
                 "version: 2");
 
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 97afa60..6c8babb 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -212,8 +212,6 @@
 
         IpConnectivityEvent got = events.get(0);
         String want = joinLines(
-                "time_ms: 0",
-                "transport: 0",
                 "connect_statistics <",
                 "  connect_count: 12",
                 "  errnos_counters <",
@@ -247,7 +245,10 @@
                 "  latencies_ms: 67",
                 "  latencies_ms: 110",
                 "  latencies_ms: 214",
-                "  latencies_ms: 523");
+                "  latencies_ms: 523",
+                ">",
+                "time_ms: 0",
+                "transport: 0");
         verifyConnectEvent(want, got);
     }
 
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index f87f6c5..29c933a 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -36,20 +36,18 @@
 
 built_ext_dep := $(call java-lib-deps,ext)
 built_ext_classes := $(call java-lib-files,ext)
-built_ext_data := $(call intermediates-dir-for, \
-			JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
+
 built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
 built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
 
-built_layoutlib_create_jar := $(call intermediates-dir-for, \
-			JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
+built_layoutlib_create_jar := $(call java-lib-files,layoutlib_create,HOST)
 
 # This is mostly a copy of config/host_java_library.mk
 LOCAL_MODULE := temp_layoutlib
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX)
 LOCAL_IS_HOST_MODULE := true
-LOCAL_BUILT_MODULE_STEM := javalib.jar
+LOCAL_BUILT_MODULE_STEM := classes.jar
 
 #######################################
 include $(BUILD_SYSTEM)/base_rules.mk
@@ -59,7 +57,6 @@
                        $(built_core_dep) \
                        $(built_framework_dep) \
                        $(built_ext_dep) \
-                       $(built_ext_data) \
 		       $(built_icudata_dep) \
 		       $(built_icutzdata_dep) \
                        $(built_layoutlib_create_jar)