Merge "Document delayed permission backup mechanism"
diff --git a/Android.bp b/Android.bp
index e14281a..b4ce5de 100644
--- a/Android.bp
+++ b/Android.bp
@@ -226,6 +226,7 @@
         "core/java/android/net/INetworkScoreService.aidl",
         "core/java/android/net/INetworkStatsService.aidl",
         "core/java/android/net/INetworkStatsSession.aidl",
+        "core/java/android/net/ITestNetworkManager.aidl",
         "core/java/android/net/ITetheringEventCallback.aidl",
         "core/java/android/net/ITetheringStatsProvider.aidl",
         "core/java/android/net/nsd/INsdManager.aidl",
@@ -605,6 +606,7 @@
         "telephony/java/com/android/internal/telephony/IOns.aidl",
         "telephony/java/com/android/internal/telephony/ITelephony.aidl",
         "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
+        "telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl",
         "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
         "telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index e363f71..0aa2563 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34676,46 +34676,46 @@
 
   public class Handler {
     ctor public Handler();
-    ctor public Handler(android.os.Handler.Callback);
-    ctor public Handler(android.os.Looper);
-    ctor public Handler(android.os.Looper, android.os.Handler.Callback);
+    ctor public Handler(@Nullable android.os.Handler.Callback);
+    ctor public Handler(@NonNull android.os.Looper);
+    ctor public Handler(@NonNull android.os.Looper, @Nullable android.os.Handler.Callback);
     method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper);
     method @NonNull public static android.os.Handler createAsync(@NonNull android.os.Looper, @NonNull android.os.Handler.Callback);
-    method public void dispatchMessage(android.os.Message);
-    method public final void dump(android.util.Printer, String);
-    method public final android.os.Looper getLooper();
-    method public String getMessageName(android.os.Message);
-    method public void handleMessage(android.os.Message);
-    method public final boolean hasCallbacks(Runnable);
+    method public void dispatchMessage(@NonNull android.os.Message);
+    method public final void dump(@NonNull android.util.Printer, @NonNull String);
+    method @NonNull public final android.os.Looper getLooper();
+    method @NonNull public String getMessageName(@NonNull android.os.Message);
+    method public void handleMessage(@NonNull android.os.Message);
+    method public final boolean hasCallbacks(@NonNull Runnable);
     method public final boolean hasMessages(int);
-    method public final boolean hasMessages(int, Object);
-    method public final android.os.Message obtainMessage();
-    method public final android.os.Message obtainMessage(int);
-    method public final android.os.Message obtainMessage(int, Object);
-    method public final android.os.Message obtainMessage(int, int, int);
-    method public final android.os.Message obtainMessage(int, int, int, Object);
-    method public final boolean post(Runnable);
-    method public final boolean postAtFrontOfQueue(Runnable);
-    method public final boolean postAtTime(Runnable, long);
-    method public final boolean postAtTime(Runnable, Object, long);
-    method public final boolean postDelayed(Runnable, long);
-    method public final boolean postDelayed(Runnable, Object, long);
-    method public final void removeCallbacks(Runnable);
-    method public final void removeCallbacks(Runnable, Object);
-    method public final void removeCallbacksAndMessages(Object);
+    method public final boolean hasMessages(int, @Nullable Object);
+    method @NonNull public final android.os.Message obtainMessage();
+    method @NonNull public final android.os.Message obtainMessage(int);
+    method @NonNull public final android.os.Message obtainMessage(int, @Nullable Object);
+    method @NonNull public final android.os.Message obtainMessage(int, int, int);
+    method @NonNull public final android.os.Message obtainMessage(int, int, int, @Nullable Object);
+    method public final boolean post(@NonNull Runnable);
+    method public final boolean postAtFrontOfQueue(@NonNull Runnable);
+    method public final boolean postAtTime(@NonNull Runnable, long);
+    method public final boolean postAtTime(@NonNull Runnable, @Nullable Object, long);
+    method public final boolean postDelayed(@NonNull Runnable, long);
+    method public final boolean postDelayed(@NonNull Runnable, @Nullable Object, long);
+    method public final void removeCallbacks(@NonNull Runnable);
+    method public final void removeCallbacks(@NonNull Runnable, @Nullable Object);
+    method public final void removeCallbacksAndMessages(@Nullable Object);
     method public final void removeMessages(int);
-    method public final void removeMessages(int, Object);
+    method public final void removeMessages(int, @Nullable Object);
     method public final boolean sendEmptyMessage(int);
     method public final boolean sendEmptyMessageAtTime(int, long);
     method public final boolean sendEmptyMessageDelayed(int, long);
-    method public final boolean sendMessage(android.os.Message);
-    method public final boolean sendMessageAtFrontOfQueue(android.os.Message);
-    method public boolean sendMessageAtTime(android.os.Message, long);
-    method public final boolean sendMessageDelayed(android.os.Message, long);
+    method public final boolean sendMessage(@NonNull android.os.Message);
+    method public final boolean sendMessageAtFrontOfQueue(@NonNull android.os.Message);
+    method public boolean sendMessageAtTime(@NonNull android.os.Message, long);
+    method public final boolean sendMessageDelayed(@NonNull android.os.Message, long);
   }
 
   public static interface Handler.Callback {
-    method public boolean handleMessage(android.os.Message);
+    method public boolean handleMessage(@NonNull android.os.Message);
   }
 
   public class HandlerThread extends java.lang.Thread {
@@ -44307,6 +44307,7 @@
     field public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
     field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
     field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
+    field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
     field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
     field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
     field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -44597,7 +44598,7 @@
   public class MbmsGroupCallSession implements java.lang.AutoCloseable {
     method public void close();
     method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
-    method public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
+    method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
     method @Nullable public android.telephony.mbms.GroupCall startGroupCall(long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.GroupCallCallback);
   }
 
@@ -44965,9 +44966,9 @@
     method public String getIccId();
     method public int getIconTint();
     method @Deprecated public int getMcc();
-    method public String getMccString();
+    method @Nullable public String getMccString();
     method @Deprecated public int getMnc();
-    method public String getMncString();
+    method @Nullable public String getMncString();
     method public String getNumber();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
@@ -45166,7 +45167,7 @@
     method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
-    method public boolean updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>);
+    method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
     field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED";
@@ -45259,6 +45260,11 @@
     field public static final int UNINITIALIZED_CARD_ID = -2; // 0xfffffffe
     field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
     field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
+    field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+    field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+    field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+    field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
+    field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
     field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
     field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
     field public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";
@@ -58057,7 +58063,7 @@
   public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
     ctor public DelegateLastClassLoader(String, ClassLoader);
     ctor public DelegateLastClassLoader(String, String, ClassLoader);
-    ctor public DelegateLastClassLoader(String, String, ClassLoader, boolean);
+    ctor public DelegateLastClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, boolean);
   }
 
   public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
diff --git a/api/test-current.txt b/api/test-current.txt
index 0bceddc..b0e8df8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1233,6 +1233,21 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
   }
 
+  public final class TestNetworkInterface implements android.os.Parcelable {
+    ctor public TestNetworkInterface(android.os.ParcelFileDescriptor, String);
+    method public int describeContents();
+    method public android.os.ParcelFileDescriptor getFileDescriptor();
+    method public String getInterfaceName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
+  }
+
+  public class TestNetworkManager {
+    method public android.net.TestNetworkInterface createTunInterface(@NonNull android.net.LinkAddress[]);
+    method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+    method public void teardownTestNetwork(@NonNull android.net.Network);
+  }
+
   public class TrafficStats {
     method public static long getLoopbackRxBytes();
     method public static long getLoopbackRxPackets();
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 8eae2b4..58b6aea 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -75,8 +75,8 @@
      * @param c2 the second array of capabilities to compare
      * @return true if both arrays contain same capabilities
      */
-    private static boolean sameCapabilities(BluetoothCodecConfig[] c1,
-                                            BluetoothCodecConfig[] c2) {
+    public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
+                                           BluetoothCodecConfig[] c2) {
         if (c1 == null) {
             return (c2 == null);
         }
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 565cd33..633966c 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1303,7 +1303,7 @@
 
     @AnyRes
     static int getAttributeSetSourceResId(@Nullable AttributeSet set) {
-        if (set == null) {
+        if (set == null || !(set instanceof XmlBlock.Parser)) {
             return ID_NULL;
         }
         return ((XmlBlock.Parser) set).getSourceResId();
diff --git a/core/java/android/net/DnsPacket.java b/core/java/android/net/DnsPacket.java
index 458fb34..0ac02b1 100644
--- a/core/java/android/net/DnsPacket.java
+++ b/core/java/android/net/DnsPacket.java
@@ -28,7 +28,6 @@
 import java.text.FieldPosition;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.StringJoiner;
 
 /**
  * Defines basic data for DNS protocol based on RFC 1035.
@@ -42,7 +41,7 @@
         public final int id;
         public final int flags;
         public final int rcode;
-        private final int[] mSectionCount;
+        private final int[] mRecordCount;
 
         /**
          * Create a new DnsHeader from a positioned ByteBuffer.
@@ -52,27 +51,32 @@
          * When this constructor returns, the reading position of the ByteBuffer has been
          * advanced to the end of the DNS header record.
          * This is meant to chain with other methods reading a DNS response in sequence.
-         *
          */
         DnsHeader(@NonNull ByteBuffer buf) throws BufferUnderflowException {
             id = BitUtils.uint16(buf.getShort());
             flags = BitUtils.uint16(buf.getShort());
             rcode = flags & 0xF;
-            mSectionCount = new int[NUM_SECTIONS];
+            mRecordCount = new int[NUM_SECTIONS];
             for (int i = 0; i < NUM_SECTIONS; ++i) {
-                mSectionCount[i] = BitUtils.uint16(buf.getShort());
+                mRecordCount[i] = BitUtils.uint16(buf.getShort());
             }
         }
 
         /**
-         * Get section count by section type.
+         * Get record count by type.
          */
-        public int getSectionCount(int sectionType) {
-            return mSectionCount[sectionType];
+        public int getRecordCount(int type) {
+            return mRecordCount[type];
         }
     }
 
-    public class DnsSection {
+    /**
+     * It's used both for DNS questions and DNS resource records.
+     *
+     * DNS questions (No TTL/RDATA)
+     * DNS resource records (With TTL/RDATA)
+     */
+    public class DnsRecord {
         private static final int MAXNAMESIZE = 255;
         private static final int MAXLABELSIZE = 63;
         private static final int MAXLABELCOUNT = 128;
@@ -81,57 +85,57 @@
         private final DecimalFormat byteFormat = new DecimalFormat();
         private final FieldPosition pos = new FieldPosition(0);
 
-        private static final String TAG = "DnsSection";
+        private static final String TAG = "DnsRecord";
 
         public final String dName;
         public final int nsType;
         public final int nsClass;
         public final long ttl;
-        private final byte[] mRR;
+        private final byte[] mRdata;
 
         /**
-         * Create a new DnsSection from a positioned ByteBuffer.
+         * Create a new DnsRecord from a positioned ByteBuffer.
          *
-         * The ByteBuffer must be in network byte order (which is the default).
-         * Reads the passed ByteBuffer from its current position and decodes a DNS section.
+         * @param ByteBuffer input of record, must be in network byte order
+         *         (which is the default).
+         * Reads the passed ByteBuffer from its current position and decodes a DNS record.
          * When this constructor returns, the reading position of the ByteBuffer has been
          * advanced to the end of the DNS header record.
          * This is meant to chain with other methods reading a DNS response in sequence.
-         *
          */
-        DnsSection(int sectionType, @NonNull ByteBuffer buf)
+        DnsRecord(int recordType, @NonNull ByteBuffer buf)
                 throws BufferUnderflowException, ParseException {
             dName = parseName(buf, 0 /* Parse depth */);
             if (dName.length() > MAXNAMESIZE) {
-                throw new ParseException("Parse name fail, name size is too long");
+                throw new ParseException(
+                        "Parse name fail, name size is too long: " + dName.length());
             }
             nsType = BitUtils.uint16(buf.getShort());
             nsClass = BitUtils.uint16(buf.getShort());
 
-            if (sectionType != QDSECTION) {
+            if (recordType != QDSECTION) {
                 ttl = BitUtils.uint32(buf.getInt());
                 final int length = BitUtils.uint16(buf.getShort());
-                mRR = new byte[length];
-                buf.get(mRR);
+                mRdata = new byte[length];
+                buf.get(mRdata);
             } else {
                 ttl = 0;
-                mRR = null;
+                mRdata = null;
             }
         }
 
         /**
-         * Get a copy of rr.
+         * Get a copy of rdata.
          */
-        @Nullable public byte[] getRR() {
-            return (mRR == null) ? null : mRR.clone();
+        @Nullable
+        public byte[] getRR() {
+            return (mRdata == null) ? null : mRdata.clone();
         }
 
         /**
          * Convert label from {@code byte[]} to {@code String}
          *
-         * It follows the same converting rule as native layer.
-         * (See ns_name.c in libc)
-         *
+         * Follows the same conversion rules of the native code (ns_name.c in libc)
          */
         private String labelToString(@NonNull byte[] label) {
             final StringBuffer sb = new StringBuffer();
@@ -139,13 +143,16 @@
                 int b = BitUtils.uint8(label[i]);
                 // Control characters and non-ASCII characters.
                 if (b <= 0x20 || b >= 0x7f) {
+                    // Append the byte as an escaped decimal number, e.g., "\19" for 0x13.
                     sb.append('\\');
                     byteFormat.format(b, sb, pos);
                 } else if (b == '"' || b == '.' || b == ';' || b == '\\'
                         || b == '(' || b == ')' || b == '@' || b == '$') {
+                    // Append the byte as an escaped character, e.g., "\:" for 0x3a.
                     sb.append('\\');
                     sb.append((char) b);
                 } else {
+                    // Append the byte as a character, e.g., "a" for 0x61.
                     sb.append((char) b);
                 }
             }
@@ -154,7 +161,9 @@
 
         private String parseName(@NonNull ByteBuffer buf, int depth) throws
                 BufferUnderflowException, ParseException {
-            if (depth > MAXLABELCOUNT) throw new ParseException("Parse name fails, too many labels");
+            if (depth > MAXLABELCOUNT) {
+                throw new ParseException("Failed to parse name, too many labels");
+            }
             final int len = BitUtils.uint8(buf.get());
             final int mask = len & NAME_COMPRESSION;
             if (0 == len) {
@@ -194,7 +203,7 @@
     private static final String TAG = DnsPacket.class.getSimpleName();
 
     protected final DnsHeader mHeader;
-    protected final List<DnsSection>[] mSections;
+    protected final List<DnsRecord>[] mRecords;
 
     public static class ParseException extends Exception {
         public ParseException(String msg) {
@@ -216,18 +225,18 @@
             throw new ParseException("Parse Header fail, bad input data", e);
         }
 
-        mSections = new ArrayList[NUM_SECTIONS];
+        mRecords = new ArrayList[NUM_SECTIONS];
 
         for (int i = 0; i < NUM_SECTIONS; ++i) {
-            final int count = mHeader.getSectionCount(i);
+            final int count = mHeader.getRecordCount(i);
             if (count > 0) {
-                mSections[i] = new ArrayList(count);
+                mRecords[i] = new ArrayList(count);
             }
             for (int j = 0; j < count; ++j) {
                 try {
-                    mSections[i].add(new DnsSection(i, buffer));
+                    mRecords[i].add(new DnsRecord(i, buffer));
                 } catch (BufferUnderflowException e) {
-                    throw new ParseException("Parse section fail", e);
+                    throw new ParseException("Parse record fail", e);
                 }
             }
         }
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 6d54264..d3bc3e6 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -43,6 +43,9 @@
 /**
  * Dns resolver class for asynchronous dns querying
  *
+ * Note that if a client sends a query with more than 1 record in the question section but
+ * the remote dns server does not support this, it may not respond at all, leading to a timeout.
+ *
  */
 public final class DnsResolver {
     private static final String TAG = "DnsResolver";
@@ -226,19 +229,19 @@
             if (mHeader.rcode != 0) {
                 throw new ParseException("Response error, rcode:" + mHeader.rcode);
             }
-            if (mHeader.getSectionCount(ANSECTION) == 0) {
+            if (mHeader.getRecordCount(ANSECTION) == 0) {
                 throw new ParseException("No available answer");
             }
-            if (mHeader.getSectionCount(QDSECTION) == 0) {
+            if (mHeader.getRecordCount(QDSECTION) == 0) {
                 throw new ParseException("No question found");
             }
-            // Assume only one question per answer packet. (RFC1035)
-            mQueryType = mSections[QDSECTION].get(0).nsType;
+            // Expect only one question in question section.
+            mQueryType = mRecords[QDSECTION].get(0).nsType;
         }
 
         public @NonNull List<InetAddress> getAddresses() {
             final List<InetAddress> results = new ArrayList<InetAddress>();
-            for (final DnsSection ansSec : mSections[ANSECTION]) {
+            for (final DnsRecord ansSec : mRecords[ANSECTION]) {
                 // Only support A and AAAA, also ignore answers if query type != answer type.
                 int nsType = ansSec.nsType;
                 if (nsType != mQueryType || (nsType != TYPE_A && nsType != TYPE_AAAA)) {
diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl
new file mode 100644
index 0000000..119a30c
--- /dev/null
+++ b/core/java/android/net/ITestNetworkManager.aidl
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkAddress;
+import android.net.TestNetworkInterface;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface that allows for creation and management of test-only networks.
+ *
+ * @hide
+ */
+interface ITestNetworkManager
+{
+    TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs);
+
+    void setupTestNetwork(in String iface, in IBinder binder);
+
+    void teardownTestNetwork(int netId);
+}
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 15f4913..a1c7fce 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,12 +1,11 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
-jsharkey@android.com
 jchalard@google.com
+jsharkey@android.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
-silberst@google.com
 
 per-file SSL*, Uri*, Url* = flooey@google.com, narayan@google.com, tobiast@google.com
diff --git a/core/java/android/net/TestNetworkInterface.aidl b/core/java/android/net/TestNetworkInterface.aidl
new file mode 100644
index 0000000..e1f4f9f
--- /dev/null
+++ b/core/java/android/net/TestNetworkInterface.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 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;
+
+/** @hide */
+parcelable TestNetworkInterface;
diff --git a/core/java/android/net/TestNetworkInterface.java b/core/java/android/net/TestNetworkInterface.java
new file mode 100644
index 0000000..30e68f5
--- /dev/null
+++ b/core/java/android/net/TestNetworkInterface.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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.TestApi;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+/**
+ * This class is used to return the interface name and fd of the test interface
+ *
+ * @hide
+ */
+@TestApi
+public final class TestNetworkInterface implements Parcelable {
+    private static final String TAG = "TestNetworkInterface";
+
+    private final ParcelFileDescriptor mFileDescriptor;
+    private final String mInterfaceName;
+
+    @Override
+    public int describeContents() {
+        return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE);
+        out.writeString(mInterfaceName);
+    }
+
+    public TestNetworkInterface(ParcelFileDescriptor pfd, String intf) {
+        mFileDescriptor = pfd;
+        mInterfaceName = intf;
+    }
+
+    private TestNetworkInterface(Parcel in) {
+        mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+        mInterfaceName = in.readString();
+    }
+
+    public ParcelFileDescriptor getFileDescriptor() {
+        return mFileDescriptor;
+    }
+
+    public String getInterfaceName() {
+        return mInterfaceName;
+    }
+
+    public static final Parcelable.Creator<TestNetworkInterface> CREATOR =
+            new Parcelable.Creator<TestNetworkInterface>() {
+                public TestNetworkInterface createFromParcel(Parcel in) {
+                    return new TestNetworkInterface(in);
+                }
+
+                public TestNetworkInterface[] newArray(int size) {
+                    return new TestNetworkInterface[size];
+                }
+            };
+}
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
new file mode 100644
index 0000000..cd58e66
--- /dev/null
+++ b/core/java/android/net/TestNetworkManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Class that allows creation and management of per-app, test-only networks
+ *
+ * @hide
+ */
+@TestApi
+public class TestNetworkManager {
+    @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName();
+
+    @NonNull private final ITestNetworkManager mService;
+    @NonNull private final Context mContext;
+
+    /** @hide */
+    public TestNetworkManager(@NonNull Context context, @NonNull ITestNetworkManager service) {
+        mContext = Preconditions.checkNotNull(context, "missing Context");
+        mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager");
+    }
+
+    /**
+     * Teardown the capability-limited, testing-only network for a given interface
+     *
+     * @param network The test network that should be torn down
+     * @hide
+     */
+    @TestApi
+    public void teardownTestNetwork(@NonNull Network network) {
+        try {
+            mService.teardownTestNetwork(network.netId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets up a capability-limited, testing-only network for a given interface
+     *
+     * @param iface the name of the interface to be used for the Network LinkProperties.
+     * @param binder A binder object guarding the lifecycle of this test network.
+     * @hide
+     */
+    @TestApi
+    public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+        try {
+            mService.setupTestNetwork(iface, binder);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Create a tun interface for testing purposes
+     *
+     * @param linkAddrs an array of LinkAddresses to assign to the TUN interface
+     * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the
+     *     TUN interface.
+     * @hide
+     */
+    @TestApi
+    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+        try {
+            return mService.createTunInterface(linkAddrs);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index b3e35b6..fea69c0 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -389,7 +389,7 @@
 
     /** {@hide} */
     public static File getDataStagingDirectory(String volumeUuid) {
-        return new File(getDataDirectory(volumeUuid), "pkg_staging");
+        return new File(getDataDirectory(volumeUuid), "app-staging");
     }
 
     /** {@hide} */
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index e6c12c7..a039742 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -82,19 +82,19 @@
          * @param msg A {@link android.os.Message Message} object
          * @return True if no further handling is desired
          */
-        public boolean handleMessage(Message msg);
+        boolean handleMessage(@NonNull Message msg);
     }
     
     /**
      * Subclasses must implement this to receive messages.
      */
-    public void handleMessage(Message msg) {
+    public void handleMessage(@NonNull Message msg) {
     }
     
     /**
      * Handle system messages here.
      */
-    public void dispatchMessage(Message msg) {
+    public void dispatchMessage(@NonNull Message msg) {
         if (msg.callback != null) {
             handleCallback(msg);
         } else {
@@ -128,7 +128,7 @@
      *
      * @param callback The callback interface in which to handle messages, or null.
      */
-    public Handler(Callback callback) {
+    public Handler(@Nullable Callback callback) {
         this(callback, false);
     }
 
@@ -137,7 +137,7 @@
      *
      * @param looper The looper, must not be null.
      */
-    public Handler(Looper looper) {
+    public Handler(@NonNull Looper looper) {
         this(looper, null, false);
     }
 
@@ -148,7 +148,7 @@
      * @param looper The looper, must not be null.
      * @param callback The callback interface in which to handle messages, or null.
      */
-    public Handler(Looper looper, Callback callback) {
+    public Handler(@NonNull Looper looper, @Nullable Callback callback) {
         this(looper, callback, false);
     }
 
@@ -189,7 +189,7 @@
      *
      * @hide
      */
-    public Handler(Callback callback, boolean async) {
+    public Handler(@Nullable Callback callback, boolean async) {
         if (FIND_POTENTIAL_LEAKS) {
             final Class<? extends Handler> klass = getClass();
             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
@@ -229,7 +229,7 @@
      *
      * @hide
      */
-    public Handler(Looper looper, Callback callback, boolean async) {
+    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
         mLooper = looper;
         mQueue = looper.mQueue;
         mCallback = callback;
@@ -289,7 +289,8 @@
     }
 
     /** {@hide} */
-    public String getTraceName(Message message) {
+    @NonNull
+    public String getTraceName(@NonNull Message message) {
         final StringBuilder sb = new StringBuilder();
         sb.append(getClass().getName()).append(": ");
         if (message.callback != null) {
@@ -308,7 +309,8 @@
      *  
      * @param message The message whose name is being queried 
      */
-    public String getMessageName(Message message) {
+    @NonNull
+    public String getMessageName(@NonNull Message message) {
         if (message.callback != null) {
             return message.callback.getClass().getName();
         }
@@ -320,6 +322,7 @@
      * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
      *  If you don't want that facility, just call Message.obtain() instead.
      */
+    @NonNull
     public final Message obtainMessage()
     {
         return Message.obtain(this);
@@ -331,6 +334,7 @@
      * @param what Value to assign to the returned Message.what field.
      * @return A Message from the global message pool.
      */
+    @NonNull
     public final Message obtainMessage(int what)
     {
         return Message.obtain(this, what);
@@ -345,8 +349,8 @@
      * @param obj Value to assign to the returned Message.obj field.
      * @return A Message from the global message pool.
      */
-    public final Message obtainMessage(int what, Object obj)
-    {
+    @NonNull
+    public final Message obtainMessage(int what, @Nullable Object obj) {
         return Message.obtain(this, what, obj);
     }
 
@@ -359,6 +363,7 @@
      * @param arg2 Value to assign to the returned Message.arg2 field.
      * @return A Message from the global message pool.
      */
+    @NonNull
     public final Message obtainMessage(int what, int arg1, int arg2)
     {
         return Message.obtain(this, what, arg1, arg2);
@@ -374,8 +379,8 @@
      * @param obj Value to assign to the returned Message.obj field.
      * @return A Message from the global message pool.
      */
-    public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
-    {
+    @NonNull
+    public final Message obtainMessage(int what, int arg1, int arg2, @Nullable Object obj) {
         return Message.obtain(this, what, arg1, arg2, obj);
     }
 
@@ -390,8 +395,7 @@
      *         message queue.  Returns false on failure, usually because the
      *         looper processing the message queue is exiting.
      */
-    public final boolean post(Runnable r)
-    {
+    public final boolean post(@NonNull Runnable r) {
        return  sendMessageDelayed(getPostMessage(r), 0);
     }
     
@@ -413,8 +417,7 @@
      *         the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public final boolean postAtTime(Runnable r, long uptimeMillis)
-    {
+    public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
         return sendMessageAtTime(getPostMessage(r), uptimeMillis);
     }
     
@@ -440,8 +443,8 @@
      *         
      * @see android.os.SystemClock#uptimeMillis
      */
-    public final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
-    {
+    public final boolean postAtTime(
+            @NonNull Runnable r, @Nullable Object token, long uptimeMillis) {
         return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
     }
     
@@ -464,8 +467,7 @@
      *         if the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public final boolean postDelayed(Runnable r, long delayMillis)
-    {
+    public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
         return sendMessageDelayed(getPostMessage(r), delayMillis);
     }
     
@@ -495,8 +497,8 @@
      *         if the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public final boolean postDelayed(Runnable r, Object token, long delayMillis)
-    {
+    public final boolean postDelayed(
+            @NonNull Runnable r, @Nullable Object token, long delayMillis) {
         return sendMessageDelayed(getPostMessage(r, token), delayMillis);
     }
 
@@ -515,8 +517,7 @@
      *         message queue.  Returns false on failure, usually because the
      *         looper processing the message queue is exiting.
      */
-    public final boolean postAtFrontOfQueue(Runnable r)
-    {
+    public final boolean postAtFrontOfQueue(@NonNull Runnable r) {
         return sendMessageAtFrontOfQueue(getPostMessage(r));
     }
 
@@ -560,7 +561,7 @@
      * If we ever do make it part of the API, we might want to rename it to something
      * less funny like runUnsafe().
      */
-    public final boolean runWithScissors(final Runnable r, long timeout) {
+    public final boolean runWithScissors(@NonNull Runnable r, long timeout) {
         if (r == null) {
             throw new IllegalArgumentException("runnable must not be null");
         }
@@ -580,8 +581,7 @@
     /**
      * Remove any pending posts of Runnable r that are in the message queue.
      */
-    public final void removeCallbacks(Runnable r)
-    {
+    public final void removeCallbacks(@NonNull Runnable r) {
         mQueue.removeMessages(this, r, null);
     }
 
@@ -590,8 +590,7 @@
      * <var>token</var> that are in the message queue.  If <var>token</var> is null,
      * all callbacks will be removed.
      */
-    public final void removeCallbacks(Runnable r, Object token)
-    {
+    public final void removeCallbacks(@NonNull Runnable r, @Nullable Object token) {
         mQueue.removeMessages(this, r, token);
     }
 
@@ -604,8 +603,7 @@
      *         message queue.  Returns false on failure, usually because the
      *         looper processing the message queue is exiting.
      */
-    public final boolean sendMessage(Message msg)
-    {
+    public final boolean sendMessage(@NonNull Message msg) {
         return sendMessageDelayed(msg, 0);
     }
 
@@ -664,8 +662,7 @@
      *         the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public final boolean sendMessageDelayed(Message msg, long delayMillis)
-    {
+    public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
         if (delayMillis < 0) {
             delayMillis = 0;
         }
@@ -691,7 +688,7 @@
      *         the looper is quit before the delivery time of the message
      *         occurs then the message will be dropped.
      */
-    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+    public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
         MessageQueue queue = mQueue;
         if (queue == null) {
             RuntimeException e = new RuntimeException(
@@ -714,7 +711,7 @@
      *         message queue.  Returns false on failure, usually because the
      *         looper processing the message queue is exiting.
      */
-    public final boolean sendMessageAtFrontOfQueue(Message msg) {
+    public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
         MessageQueue queue = mQueue;
         if (queue == null) {
             RuntimeException e = new RuntimeException(
@@ -734,7 +731,7 @@
      *         looper processing the message queue is exiting.
      * @hide
      */
-    public final boolean executeOrSendMessage(Message msg) {
+    public final boolean executeOrSendMessage(@NonNull Message msg) {
         if (mLooper == Looper.myLooper()) {
             dispatchMessage(msg);
             return true;
@@ -742,7 +739,8 @@
         return sendMessage(msg);
     }
 
-    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
+    private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
+            long uptimeMillis) {
         msg.target = this;
         msg.workSourceUid = ThreadLocalWorkSource.getUid();
 
@@ -765,7 +763,7 @@
      * 'object' that are in the message queue.  If <var>object</var> is null,
      * all messages will be removed.
      */
-    public final void removeMessages(int what, Object object) {
+    public final void removeMessages(int what, @Nullable Object object) {
         mQueue.removeMessages(this, what, object);
     }
 
@@ -774,7 +772,7 @@
      * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
      * all callbacks and messages will be removed.
      */
-    public final void removeCallbacksAndMessages(Object token) {
+    public final void removeCallbacksAndMessages(@Nullable Object token) {
         mQueue.removeCallbacksAndMessages(this, token);
     }
 
@@ -798,7 +796,7 @@
      * Check if there are any pending posts of messages with code 'what' and
      * whose obj is 'object' in the message queue.
      */
-    public final boolean hasMessages(int what, Object object) {
+    public final boolean hasMessages(int what, @Nullable Object object) {
         return mQueue.hasMessages(this, what, object);
     }
 
@@ -806,17 +804,18 @@
      * Check if there are any pending posts of messages with callback r in
      * the message queue.
      */
-    public final boolean hasCallbacks(Runnable r) {
+    public final boolean hasCallbacks(@NonNull Runnable r) {
         return mQueue.hasMessages(this, r, null);
     }
 
     // if we can get rid of this method, the handler need not remember its loop
     // we could instead export a getMessageQueue() method... 
+    @NonNull
     public final Looper getLooper() {
         return mLooper;
     }
 
-    public final void dump(Printer pw, String prefix) {
+    public final void dump(@NonNull Printer pw, @NonNull String prefix) {
         pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
         if (mLooper == null) {
             pw.println(prefix + "looper uninitialized");
@@ -828,7 +827,7 @@
     /**
      * @hide
      */
-    public final void dumpMine(Printer pw, String prefix) {
+    public final void dumpMine(@NonNull Printer pw, @NonNull String prefix) {
         pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
         if (mLooper == null) {
             pw.println(prefix + "looper uninitialized");
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index cb794ad..2143a0d 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -471,10 +471,12 @@
      * the most recently modified documents.
      * <p>
      * If this method is overriden by the concrete DocumentsProvider and
-     * QUERY_ARGS_LIMIT is specified with a nonnegative int under queryArgs, the
-     * result will be limited by that number and QUERY_ARG_LIMIT will be
-     * specified under EXTRA_HONORED_ARGS. Otherwise, a default 64 limit will
-     * be used and no QUERY_ARG* will be specified under EXTRA_HONORED_ARGS.
+     * {@link ContentResolver#QUERY_ARG_LIMIT} is specified with a nonnegative
+     * int under queryArgs, the result will be limited by that number and
+     * {@link ContentResolver#QUERY_ARG_LIMIT} will be specified under
+     * {@link ContentResolver#EXTRA_HONORED_ARGS}. Otherwise, a default 64 limit
+     * will be used and no QUERY_ARG* will be specified under
+     * {@link ContentResolver#EXTRA_HONORED_ARGS}.
      * <p>
      * Recent documents do not support change notifications.
      *
diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
index 86f99bb..45a8466 100644
--- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
+++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java
@@ -185,7 +185,7 @@
 
     /**
      * For temporary compat reason, remove with b/127532182
-     * @deprecated
+     * @deprecated use {@link #onProcessContextImage(int, Bitmap, Bundle)} instead.
      */
     @Deprecated
     public void processContextImage(
@@ -194,7 +194,8 @@
 
     /**
      * For temporary compat reason, remove with b/127532182
-     * @deprecated
+     * @deprecated use {@link #onSuggestContentSelections(SelectionsRequest,
+     * ContentSuggestionsManager.SelectionsCallback)} instead.
      */
     @Deprecated
     public void suggestContentSelections(@NonNull SelectionsRequest request,
@@ -203,7 +204,8 @@
 
     /**
      * For temporary compat reason, remove with b/127532182
-     * @deprecated
+     * @deprecated use {@link #onClassifyContentSelections(ClassificationsRequest,
+     * ContentSuggestionsManager.ClassificationsCallback)} instead.
      */
     @Deprecated
     public void classifyContentSelections(@NonNull ClassificationsRequest request,
@@ -212,7 +214,7 @@
 
     /**
      * For temporary compat reason, remove with b/127532182
-     * @deprecated
+     * @deprecated use {@link #onNotifyInteraction(String, Bundle)} instead.
      */
     @Deprecated
     public void notifyInteraction(@NonNull String requestId, @NonNull Bundle interaction) {
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b99336b..7747a55 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -48,7 +48,7 @@
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
-        DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
+        DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
         DEFAULT_FLAGS.put("settings_slice_injection", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
         DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 6eceb003..24f1fb5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7794,6 +7794,11 @@
                 mLastSeenPos = firstPos;
 
                 final int childCount = getChildCount();
+
+                if (childCount <= 0) {
+                    return;
+                }
+
                 final int position = mTargetPos;
                 final int lastPos = firstPos + childCount - 1;
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index fd978f5..91928b5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -420,6 +420,10 @@
                 if (isFinishing() || isDestroyed()) {
                     return;
                 }
+                // May be null if there are no apps to perform share/open action.
+                if (mChooserListAdapter == null) {
+                    return;
+                }
                 final List<DisplayResolveInfo> driList =
                         getDisplayResolveInfos(mChooserListAdapter);
                 final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java
index d6a8934..9d85a03 100644
--- a/core/java/com/android/internal/colorextraction/types/Tonal.java
+++ b/core/java/com/android/internal/colorextraction/types/Tonal.java
@@ -56,7 +56,6 @@
 
     private final TonalPalette mGreyPalette;
     private final ArrayList<TonalPalette> mTonalPalettes;
-    private final ArrayList<ColorRange> mBlacklistedColors;
 
     // Temporary variable to avoid allocations
     private float[] mTmpHSL = new float[3];
@@ -65,7 +64,6 @@
 
         ConfigParser parser = new ConfigParser(context);
         mTonalPalettes = parser.getTonalPalettes();
-        mBlacklistedColors = parser.getBlacklistedColors();
 
         mGreyPalette = mTonalPalettes.get(0);
         mTonalPalettes.remove(0);
@@ -131,7 +129,7 @@
                     Color.blue(colorValue), hsl);
 
             // Stop when we find a color that meets our criteria
-            if (!generatedFromBitmap || !isBlacklisted(hsl)) {
+            if (!generatedFromBitmap) {
                 bestColor = color;
                 break;
             }
@@ -300,22 +298,6 @@
         return getColorPalette(palette.h, palette.s, palette.l);
     }
 
-
-    /**
-     * Checks if a given color exists in the blacklist
-     * @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1)
-     * @return true if color should be avoided
-     */
-    private boolean isBlacklisted(float[] hsl) {
-        for (int i = mBlacklistedColors.size() - 1; i >= 0; i--) {
-            ColorRange badRange = mBlacklistedColors.get(i);
-            if (badRange.containsColor(hsl[0], hsl[1], hsl[2])) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /**
      * Offsets all colors by a delta, clamping values that go beyond what's
      * supported on the color space.
@@ -364,11 +346,6 @@
         return minErrorIndex;
     }
 
-    @VisibleForTesting
-    public List<ColorRange> getBlacklistedColors() {
-        return mBlacklistedColors;
-    }
-
     @Nullable
     private TonalPalette findTonalPalette(float h, float s) {
         // Fallback to a grey palette if the color is too desaturated.
@@ -502,11 +479,9 @@
     @VisibleForTesting
     public static class ConfigParser {
         private final ArrayList<TonalPalette> mTonalPalettes;
-        private final ArrayList<ColorRange> mBlacklistedColors;
 
         public ConfigParser(Context context) {
             mTonalPalettes = new ArrayList<>();
-            mBlacklistedColors = new ArrayList<>();
 
             // Load all palettes and the blacklist from an XML.
             try {
@@ -520,8 +495,6 @@
                         String tagName = parser.getName();
                         if (tagName.equals("palettes")) {
                             parsePalettes(parser);
-                        } else if (tagName.equals("blacklist")) {
-                            parseBlacklist(parser);
                         }
                     } else {
                         throw new XmlPullParserException("Invalid XML event " + eventType + " - "
@@ -538,28 +511,6 @@
             return mTonalPalettes;
         }
 
-        public ArrayList<ColorRange> getBlacklistedColors() {
-            return mBlacklistedColors;
-        }
-
-        private void parseBlacklist(XmlPullParser parser)
-                throws XmlPullParserException, IOException {
-            parser.require(XmlPullParser.START_TAG, null, "blacklist");
-            while (parser.next() != XmlPullParser.END_TAG) {
-                if (parser.getEventType() != XmlPullParser.START_TAG) {
-                    continue;
-                }
-                String name = parser.getName();
-                // Starts by looking for the entry tag
-                if (name.equals("range")) {
-                    mBlacklistedColors.add(readRange(parser));
-                    parser.next();
-                } else {
-                    throw new XmlPullParserException("Invalid tag: " + name, parser, null);
-                }
-            }
-        }
-
         private ColorRange readRange(XmlPullParser parser)
                 throws XmlPullParserException, IOException {
             parser.require(XmlPullParser.START_TAG, null, "range");
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index ec02432..940cc36 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -18,6 +18,8 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
+import android.net.ProxyInfo;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -46,6 +48,10 @@
     public static final int TYPE_IPSEC_HYBRID_RSA = 5;
     public static final int TYPE_MAX = 5;
 
+    // Match these constants with R.array.vpn_proxy_settings.
+    public static final int PROXY_NONE = 0;
+    public static final int PROXY_MANUAL = 1;
+
     // Entity fields.
     @UnsupportedAppUsage
     public final String key;           // -1
@@ -68,6 +74,7 @@
     public String ipsecUserCert = "";  // 12
     public String ipsecCaCert = "";    // 13
     public String ipsecServerCert = "";// 14
+    public ProxyInfo proxy = null;     // 15~18
 
     // Helper fields.
     @UnsupportedAppUsage
@@ -96,6 +103,7 @@
         ipsecCaCert = in.readString();
         ipsecServerCert = in.readString();
         saveLogin = in.readInt() != 0;
+        proxy = in.readParcelable(null);
     }
 
     @Override
@@ -117,6 +125,7 @@
         out.writeString(ipsecCaCert);
         out.writeString(ipsecServerCert);
         out.writeInt(saveLogin ? 1 : 0);
+        out.writeParcelable(proxy, flags);
     }
 
     @UnsupportedAppUsage
@@ -127,8 +136,8 @@
             }
 
             String[] values = new String(value, StandardCharsets.UTF_8).split("\0", -1);
-            // There can be 14 or 15 values in ICS MR1.
-            if (values.length < 14 || values.length > 15) {
+            // There can be 14 - 19 Bytes in values.length.
+            if (values.length < 14 || values.length > 19) {
                 return null;
             }
 
@@ -151,7 +160,18 @@
             profile.ipsecUserCert = values[12];
             profile.ipsecCaCert = values[13];
             profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
-
+            if (values.length > 15) {
+                String host = (values.length > 15) ? values[15] : "";
+                String port = (values.length > 16) ? values[16] : "";
+                String exclList = (values.length > 17) ? values[17] : "";
+                String pacFileUrl = (values.length > 18) ? values[18] : "";
+                if (pacFileUrl.isEmpty()) {
+                    profile.proxy = new ProxyInfo(host, port.isEmpty() ?
+                            0 : Integer.parseInt(port), exclList);
+                } else {
+                    profile.proxy = new ProxyInfo(pacFileUrl);
+                }
+            } // else profle.proxy = null
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
         } catch (Exception e) {
@@ -176,6 +196,13 @@
         builder.append('\0').append(ipsecUserCert);
         builder.append('\0').append(ipsecCaCert);
         builder.append('\0').append(ipsecServerCert);
+        if (proxy != null) {
+            builder.append('\0').append(proxy.getHost() != null ? proxy.getHost() : "");
+            builder.append('\0').append(proxy.getPort());
+            builder.append('\0').append(proxy.getExclusionListAsString() != null ?
+                    proxy.getExclusionListAsString() : "");
+            builder.append('\0').append(proxy.getPacFileUrl().toString());
+        }
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
 
diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS
index 7311eee..d3836d4 100644
--- a/core/java/com/android/server/net/OWNERS
+++ b/core/java/com/android/server/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5b658b7..6671ff8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -707,12 +707,12 @@
     <string name="permgrouprequest_location">Allow
         &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\'s location?</string>
     <!-- Subtitle of the message shown to the user when the apps requests permission to use the location only while app is in foreground [CHAR LIMIT=150]-->
-    <string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app.</string>
+    <string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app</string>
     <!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
-    <string name="permgroupbackgroundrequest_location">Always allow
-        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location?</string>
+    <string name="permgroupbackgroundrequest_location">Allow
+        &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location &lt;b>all the time&lt;/b>?</string>
     <!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background [CHAR LIMIT=150] -->
-    <string name="permgroupbackgroundrequestdetail_location">The app will always have access to the location, even when you\u2019re not using the app.</string>
+    <string name="permgroupbackgroundrequestdetail_location">App currently can access location only while you\u2019re using the app</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_calendar">Calendar</string>
diff --git a/core/res/res/xml/color_extraction.xml b/core/res/res/xml/color_extraction.xml
index 93ab0ff..c3ebe4e 100644
--- a/core/res/res/xml/color_extraction.xml
+++ b/core/res/res/xml/color_extraction.xml
@@ -246,109 +246,4 @@
                 0.6549019607843137,0.7549019607843137,0.8509803921568627,
                 0.9411764705882353"/>
     </palettes>
-    <blacklist>
-        <!-- Red -->
-        <range h="0, 20"
-               s="0.7, 1"
-               l="0.21, 0.79"/>
-        <range h="0, 20"
-               s="0.3, 0.7"
-               l="0.355, 0.653"/>
-        <!-- Red Orange -->
-        <range h="20, 40"
-               s="0.7, 1"
-               l="0.2, 0.643"/>
-        <range h="20, 40"
-               s="0.3, 0.7"
-               l="0.414, 0.561"/>
-        <range h="20, 40"
-               s="0, 0.3"
-               l="0.343, 0.584"/>
-        <!-- Orange -->
-        <range h="40, 60"
-               s="0.7, 1"
-               l="0.173, 0.38"/>
-        <range h="40, 60"
-               s="0.3, 0.7"
-               l="0.233, 0.427"/>
-        <range h="40, 60"
-               s="0, 0.3"
-               l="0.231, 0.48"/>
-        <!-- Yellow 60 -->
-        <range h="60, 80"
-               s="0.7, 1"
-               l="0.15, 0.40"/>
-        <range h="60, 80"
-               s="0.3, 0.7"
-               l="0.15, 0.42"/>
-        <range h="60, 80"
-               s="0, 0.3"
-               l="0.35, 0.57"/>
-        <!-- Yellow Green 80 -->
-        <range h="80, 100"
-               s="0.7, 1"
-               l="0.36, 0.65"/>
-        <range h="80, 100"
-               s="0.3, 0.7"
-               l="0.48, 0.57"/>
-        <!-- Yellow green 100 -->
-        <range h="100, 120"
-               s="0.7, 1"
-               l="0.388, 0.67"/>
-        <range h="100, 120"
-               s="0.3, 0.7"
-               l="0.424, 0.58"/>
-        <!-- Green -->
-        <range h="120, 140"
-               s="0.7, 1"
-               l="0.37, 0.65"/>
-        <range h="120, 140"
-               s="0.3, 0.7"
-               l="0.435, 0.58"/>
-        <!-- Green Blue 140 -->
-        <range h="140, 160"
-               s="0.7, 1"
-               l="0.43, 0.641"/>
-        <!-- Seaoam -->
-        <range h="160, 180"
-               s="0.7, 1"
-               l="0.496, 0.567"/>
-        <!-- Cyan -->
-        <range h="180, 200"
-               s="0.7, 1"
-               l="0.52, 0.729"/>
-        <!-- Blue -->
-        <range h="220, 240"
-               s="0.7, 1"
-               l="0.396, 0.571"/>
-        <range h="220, 240"
-               s="0.3, 0.7"
-               l="0.425, 0.551"/>
-        <!-- Blue Purple 240 -->
-        <range h="240, 260"
-               s="0.7, 1"
-               l="0.418, 0.639"/>
-        <range h="220, 240"
-               s="0.3, 0.7"
-               l="0.441, 0.576"/>
-        <!-- Blue Purple 260 -->
-        <range h="260, 280"
-               s="0.3, 1"
-               l="0.461, 0.553"/>
-        <!-- Fuchsia -->
-        <range h="300, 320"
-               s="0.7, 1"
-               l="0.484, 0.588"/>
-        <range h="300, 320"
-               s="0.3, 0.7"
-               l="0.48, 0.592"/>
-        <!-- Pink -->
-        <range h="320, 340"
-               s="0.7, 1"
-               l="0.466, 0.629"/>
-        <!-- Soft red -->
-        <range h="340, 360"
-               s="0.7, 1"
-               l="0.437, 0.596"/>
-    </blacklist>
-</colorextraction>
\ No newline at end of file
+</colorextraction>
diff --git a/native/android/OWNERS b/native/android/OWNERS
index b3f50aa..266764a 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,4 +1,4 @@
 set noparent
 
-per-file libandroid_net.map.txt, net.c = codewiz@google.com, ek@google.com, jchalard@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
 per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS
index 7311eee..d3836d4 100644
--- a/packages/CaptivePortalLogin/OWNERS
+++ b/packages/CaptivePortalLogin/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/packages/NetworkStack/OWNERS b/packages/NetworkStack/OWNERS
index a395465..0e1e65d 100644
--- a/packages/NetworkStack/OWNERS
+++ b/packages/NetworkStack/OWNERS
@@ -1,5 +1,6 @@
 codewiz@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
index 17a36ad..d1ca109 100644
--- a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.net.captiveportal.CaptivePortalProbeResult;
 import android.util.Log;
+import android.util.StatsLog;
 
 import com.android.internal.util.HexDump;
 import com.android.server.connectivity.nano.DataStallEventProto;
@@ -36,6 +37,7 @@
  */
 public class DataStallStatsUtils {
     private static final String TAG = DataStallStatsUtils.class.getSimpleName();
+    private static final int DATA_STALL_EVENT_ID = 121;
     private static final boolean DBG = false;
 
     private static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) {
@@ -61,6 +63,13 @@
             Log.d(TAG, "write: " + stats + " with result: " + validationResult
                     + ", dns: " + HexDump.toHexString(stats.mDns));
         }
-        // TODO(b/124613085): Send to Statsd once the public StatsLog API is ready.
+        // TODO(b/124613085): Update API once the public StatsLog API is ready.
+        StatsLog.write(DATA_STALL_EVENT_ID,
+                stats.mEvaluationType,
+                validationResult,
+                stats.mNetworkType,
+                stats.mWifiInfo,
+                stats.mCellularInfo,
+                stats.mDns);
     }
 }
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index f6eb900..6fbeead 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -33,7 +33,9 @@
     public static void checkNetworkStackCallingPermission() {
         // TODO: check that the calling PID is the system server.
         final int caller = getCallingUid();
-        if (caller != Process.SYSTEM_UID && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
+        if (caller != Process.SYSTEM_UID
+                && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID
+                && UserHandle.getAppId(caller) != Process.PHONE_UID) {
             throw new SecurityException("Invalid caller: " + caller);
         }
     }
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index ee2baf2..34ca6ac 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -525,7 +525,7 @@
         wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
         makeDnsTimeoutEvent(wrappedMonitor, 5);
         assertTrue(wrappedMonitor.isDataStall());
-        verify(mDataStallStatsUtils, times(1)).write(any(), any());
+        verify(mDataStallStatsUtils, times(1)).write(makeEmptyDataStallDetectionStats(), any());
     }
 
     @Test
@@ -534,7 +534,7 @@
         wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
         makeDnsTimeoutEvent(wrappedMonitor, 3);
         assertFalse(wrappedMonitor.isDataStall());
-        verify(mDataStallStatsUtils, never()).write(any(), any());
+        verify(mDataStallStatsUtils, never()).write(makeEmptyDataStallDetectionStats(), any());
     }
 
     @Test
@@ -586,6 +586,10 @@
         }
     }
 
+    private DataStallDetectionStats makeEmptyDataStallDetectionStats() {
+        return new DataStallDetectionStats.Builder().build();
+    }
+
     private void setDataStallEvaluationType(int type) {
         when(mDependencies.getSetting(any(),
             eq(Settings.Global.DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 9d6fc9ed..6df6c73 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -135,6 +135,7 @@
     <uses-permission android:name="android.permission.MANAGE_BIOMETRIC" />
     <uses-permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS" />
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" />
+    <uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
 
     <!-- Needed for WallpaperManager.clear in ImageWallpaper.updateWallpaperLocked -->
     <uses-permission android:name="android.permission.SET_WALLPAPER"/>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 10996e88..794c30a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -217,4 +217,11 @@
         WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
                 DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
     }
+
+    /**
+     * Removes a pinned stack listener.
+     */
+    public void removePinnedStackListener(IPinnedStackListener listener) {
+        mPinnedStackListenerForwarder.removeListener(listener);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 4d8cf96..59ee267 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -76,8 +76,10 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
 
-        final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX, true);
-        final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY, false);
+        final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
+                - mBurnInPreventionOffsetX;
+        final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
+                - mBurnInPreventionOffsetY;
 
         // Put digital clock in two left corner of the screen.
         if (mDigitalClock != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index c013df3..ace086f 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -20,6 +20,7 @@
 
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -203,26 +204,37 @@
     }
 
     /**
+     * Does the app-op item refer to a user sensitive permission. Only user sensitive permission
+     * should be shown to the user by default.
+     *
+     * @param item The item
+     *
+     * @return {@code true} iff the app-op item is user sensitive
+     */
+    private boolean isUserSensitive(AppOpItem item) {
+        String permission = AppOpsManager.opToPermission(item.getCode());
+        if (permission == null) {
+            return false;
+        }
+        int permFlags = mContext.getPackageManager().getPermissionFlags(permission,
+                item.getPackageName(), UserHandle.getUserHandleForUid(item.getUid()));
+        return (permFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) != 0;
+    }
+
+    /**
      * Returns a copy of the list containing all the active AppOps that the controller tracks.
      *
      * @return List of active AppOps information
      */
     public List<AppOpItem> getActiveAppOps() {
-        ArrayList<AppOpItem> active;
-        synchronized (mActiveItems) {
-            active = new ArrayList<>(mActiveItems);
-        }
-        synchronized (mNotedItems) {
-            active.addAll(mNotedItems);
-        }
-        return active;
+        return getActiveAppOpsForUser(UserHandle.USER_ALL);
     }
 
     /**
      * Returns a copy of the list containing all the active AppOps that the controller tracks, for
      * a given user id.
      *
-     * @param userId User id to track
+     * @param userId User id to track, can be {@link UserHandle#USER_ALL}
      *
      * @return List of active AppOps information for that user id
      */
@@ -232,7 +244,8 @@
             final int numActiveItems = mActiveItems.size();
             for (int i = 0; i < numActiveItems; i++) {
                 AppOpItem item = mActiveItems.get(i);
-                if (UserHandle.getUserId(item.getUid()) == userId) {
+                if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
+                        && isUserSensitive(item)) {
                     list.add(item);
                 }
             }
@@ -241,7 +254,8 @@
             final int numNotedItems = mNotedItems.size();
             for (int i = 0; i < numNotedItems; i++) {
                 AppOpItem item = mNotedItems.get(i);
-                if (UserHandle.getUserId(item.getUid()) == userId) {
+                if ((userId == UserHandle.USER_ALL || UserHandle.getUserId(item.getUid()) == userId)
+                        && isUserSensitive(item)) {
                     list.add(item);
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 51b2098..eb85589 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -23,6 +23,8 @@
 import static com.android.systemui.statusbar.StatusBarState.SHADE;
 import static com.android.systemui.statusbar.notification.NotificationAlertingManager.alertAgain;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.annotation.Nullable;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
@@ -42,6 +44,7 @@
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.IntDef;
 import androidx.annotation.MainThread;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -59,6 +62,8 @@
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
 
+import java.lang.annotation.Retention;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -70,10 +75,22 @@
  */
 @Singleton
 public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListener {
-    private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
 
     private static final String TAG = "BubbleController";
 
+    private static final int MAX_BUBBLES = 5; // TODO: actually enforce this
+
+    @Retention(SOURCE)
+    @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
+            DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION})
+    @interface DismissReason {}
+    static final int DISMISS_USER_GESTURE = 1;
+    static final int DISMISS_AGED = 2;
+    static final int DISMISS_TASK_FINISHED = 3;
+    static final int DISMISS_BLOCKED = 4;
+    static final int DISMISS_NOTIF_CANCEL = 5;
+    static final int DISMISS_ACCESSIBILITY_ACTION = 6;
+
     // Enables some subset of notifs to automatically become bubbles
     private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
 
@@ -248,11 +265,11 @@
     /**
      * Tell the stack of bubbles to be dismissed, this will remove all of the bubbles in the stack.
      */
-    void dismissStack() {
+    void dismissStack(@DismissReason int reason) {
         if (mStackView == null) {
             return;
         }
-        mStackView.stackDismissed();
+        mStackView.stackDismissed(reason);
 
         updateVisibility();
         mNotificationEntryManager.updateNotifications();
@@ -304,9 +321,9 @@
      * Must be called from the main thread.
      */
     @MainThread
-    void removeBubble(String key) {
+    void removeBubble(String key, int reason) {
         if (mStackView != null) {
-            mStackView.removeBubble(key);
+            mStackView.removeBubble(key, reason);
         }
         mNotificationEntryManager.updateNotifications();
         updateVisibility();
@@ -320,7 +337,7 @@
             boolean samePackage = entry.notification.getPackageName().equals(
                     e.notification.getPackageName());
             if (samePackage) {
-                removeBubble(entry.key);
+                removeBubble(entry.key, DISMISS_BLOCKED);
             }
         }
     }
@@ -377,7 +394,7 @@
             }
             if (!removedByUser) {
                 // This was a cancel so we should remove the bubble
-                removeBubble(entry.key);
+                removeBubble(entry.key, DISMISS_NOTIF_CANCEL);
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 25ee87a..856b9d6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -135,7 +135,8 @@
         public void onTaskRemovalStarted(int taskId) {
             if (mEntry != null) {
                 // Must post because this is called from a binder thread.
-                post(() -> mBubbleController.removeBubble(mEntry.key));
+                post(() -> mBubbleController.removeBubble(mEntry.key,
+                        BubbleController.DISMISS_TASK_FINISHED));
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 84efb9a..888e3fe 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -19,6 +19,8 @@
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import android.app.Notification;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Outline;
@@ -49,6 +51,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleController.DismissReason;
 import com.android.systemui.bubbles.animation.ExpandedAnimationController;
 import com.android.systemui.bubbles.animation.PhysicsAnimationLayout;
 import com.android.systemui.bubbles.animation.StackAnimationController;
@@ -62,6 +65,7 @@
  */
 public class BubbleStackView extends FrameLayout {
     private static final String TAG = "BubbleStackView";
+    private static final boolean DEBUG = false;
 
     private Point mDisplaySize;
 
@@ -232,7 +236,7 @@
         }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_DISMISS:
-                stackDismissed();
+                stackDismissed(BubbleController.DISMISS_ACCESSIBILITY_ACTION);
                 return true;
             case AccessibilityNodeInfo.ACTION_COLLAPSE:
                 collapseStack();
@@ -356,18 +360,12 @@
     /**
      * Remove a bubble from the stack.
      */
-    public void removeBubble(String key) {
+    public void removeBubble(String key, int reason) {
         Bubble b = mBubbleData.removeBubble(key);
         if (b == null) {
             return;
         }
-        b.entry.setBubbleDismissed(true);
-
-        // Remove it from the views
-        int removedIndex = mBubbleContainer.indexOfChild(b.iconView);
-        b.expandedView.cleanUpExpandedState();
-        mBubbleContainer.removeView(b.iconView);
-
+        int removedIndex = dismissBubble(b, reason);
         int bubbleCount = mBubbleContainer.getChildCount();
         if (bubbleCount == 0) {
             // If no bubbles remain, collapse the entire stack.
@@ -385,26 +383,63 @@
                 mExpandedBubble = null;
             }
         }
+        // TODO: consider logging reason code
         logBubbleEvent(b, StatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED);
     }
 
     /**
      * Dismiss the stack of bubbles.
      */
-    public void stackDismissed() {
+    public void stackDismissed(int reason) {
         for (Bubble bubble : mBubbleData.getBubbles()) {
-            bubble.entry.setBubbleDismissed(true);
-            bubble.expandedView.cleanUpExpandedState();
+            dismissBubble(bubble, reason);
         }
         mBubbleData.clear();
         collapseStack();
         mBubbleContainer.removeAllViews();
         mExpandedViewContainer.removeAllViews();
+        // TODO: consider logging reason code
         logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
                 StatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
     }
 
     /**
+     * Marks the notification entry as dismissed, cleans up Bubble icon and expanded view UI
+     * elements and calls deleteIntent if necessary.
+     *
+     * <p>Note: This does not remove the Bubble from BubbleData.
+     *
+     * @param bubble the Bubble being dismissed
+     * @param reason code for the reason the dismiss was triggered
+     * @see BubbleController.DismissReason
+     */
+    private int dismissBubble(Bubble bubble, @DismissReason int reason) {
+        if (DEBUG) {
+            Log.d(TAG, "dismissBubble: " + bubble + " reason=" + reason);
+        }
+        bubble.entry.setBubbleDismissed(true);
+        bubble.expandedView.cleanUpExpandedState();
+
+        // Remove it from the views
+        int removedIndex = mBubbleContainer.indexOfChild(bubble.iconView);
+        mBubbleContainer.removeViewAt(removedIndex);
+
+        if (reason == BubbleController.DISMISS_USER_GESTURE) {
+            Notification.BubbleMetadata bubbleMetadata = bubble.entry.getBubbleMetadata();
+            PendingIntent deleteIntent = bubbleMetadata.getDeleteIntent();
+            if (deleteIntent != null) {
+                try {
+                    deleteIntent.send();
+                } catch (PendingIntent.CanceledException e) {
+                    Log.w(TAG, "Failed to send delete intent for bubble with key: "
+                            + (bubble.entry != null ? bubble.entry.key : " null entry"));
+                }
+            }
+        }
+        return removedIndex;
+    }
+
+    /**
      * Updates a bubble in the stack.
      *
      * @param entry the entry to update in the stack.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index c8eebac..a7170d0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -140,7 +140,7 @@
             case MotionEvent.ACTION_UP:
                 trackMovement(event);
                 if (mInDismissTarget && isStack) {
-                    mController.dismissStack();
+                    mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
                 } else if (mMovedEnough) {
                     mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
                     final float velX = mVelocityTracker.getXVelocity();
@@ -152,7 +152,8 @@
                         mStack.onBubbleDragFinish(
                                 mTouchedView, viewX, viewY, velX, velY, /* dismissed */ dismissed);
                         if (dismissed) {
-                            mController.removeBubble(((BubbleView) mTouchedView).getKey());
+                            mController.removeBubble(((BubbleView) mTouchedView).getKey(),
+                                    BubbleController.DISMISS_USER_GESTURE);
                         }
                     }
                 } else if (mTouchedView == mStack.getExpandedBubbleView()) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 1f02607..3c4bc72 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -423,7 +423,7 @@
                 .setDampingRatio(BubbleController.getBubbleBounciness(
                         mLayout.getContext(), DEFAULT_BOUNCINESS))
                 .setStiffness(BubbleController.getBubbleStiffness(
-                        mLayout.getContext(), (int) (DEFAULT_STIFFNESS * 100f)));
+                        mLayout.getContext(), (int) DEFAULT_STIFFNESS));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index c3d4b0f..847182d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -39,7 +39,6 @@
  */
 public class DozeUi implements DozeMachine.Part {
 
-    private static final String TAG = "DozeUi";
     private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
     private final Context mContext;
     private final DozeHost mHost;
@@ -94,11 +93,13 @@
                 new DozeHost.PulseCallback() {
                     @Override
                     public void onPulseStarted() {
-                        if (mMachine.getState() != DozeMachine.State.DOZE_REQUEST_PULSE) {
-                            Log.w(TAG, "Pulse was cancelled before it could have been started");
-                            return;
+                        try {
+                            mMachine.requestState(DozeMachine.State.DOZE_PULSING);
+                        } catch (IllegalStateException e) {
+                            // It's possible that the pulse was asynchronously cancelled while
+                            // we were waiting for it to start (under stress conditions.)
+                            // In those cases we should just ignore it. b/127657926
                         }
-                        mMachine.requestState(DozeMachine.State.DOZE_PULSING);
                     }
 
                     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3273253..9b44066 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -89,6 +89,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.plugins.GlobalActionsPanelPlugin;
+import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ExtensionController;
 import com.android.systemui.statusbar.policy.ExtensionController.Extension;
@@ -1533,7 +1534,7 @@
             View panelView = initializePanel();
             if (panelView == null) {
                 mBackgroundDrawable = new GradientDrawable(context);
-                mScrimAlpha = 0.7f;
+                mScrimAlpha = ScrimController.GRADIENT_SCRIM_ALPHA;
             } else {
                 mBackgroundDrawable = context.getDrawable(
                         com.android.systemui.R.drawable.global_action_panel_scrim);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index bed0c45..341461b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -42,9 +42,11 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Matrix;
@@ -743,6 +745,15 @@
                 return (x - flashDurationPct) / (1f - flashDurationPct);
             }
         };
+
+        Resources r = mContext.getResources();
+        if ((r.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
+                == Configuration.UI_MODE_NIGHT_YES) {
+            mScreenshotView.getBackground().setTint(Color.BLACK);
+        } else {
+            mScreenshotView.getBackground().setTintList(null);
+        }
+
         ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
         anim.setDuration(SCREENSHOT_DROP_IN_DURATION);
         anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index b820dc0..a630e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -461,9 +461,6 @@
     }
 
     public boolean shouldKeepForRemoteInputHistory(NotificationEntry entry) {
-        if (entry.isDismissed()) {
-            return false;
-        }
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
@@ -471,9 +468,6 @@
     }
 
     public boolean shouldKeepForSmartReplyHistory(NotificationEntry entry) {
-        if (entry.isDismissed()) {
-            return false;
-        }
         if (!FORCE_REMOTE_INPUT_HISTORY) {
             return false;
         }
@@ -661,9 +655,6 @@
     protected class RemoteInputActiveExtender extends RemoteInputExtender {
         @Override
         public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
-            if (entry.isDismissed()) {
-                return false;
-            }
             return mRemoteInputController.isRemoteInputActive(entry);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 4ed9ae4..7d224fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -159,16 +159,19 @@
     }
 
     public void performRemoveNotification(StatusBarNotification n) {
-        final int rank = mNotificationData.getRank(n.getKey());
-        final int count = mNotificationData.getActiveNotifications().size();
-        NotificationVisibility.NotificationLocation location =
-                NotificationLogger.getNotificationLocation(getNotificationData().get(n.getKey()));
-        final NotificationVisibility nv = NotificationVisibility.obtain(n.getKey(), rank, count,
-                true, location);
+        final NotificationVisibility nv = obtainVisibility(n.getKey());
         removeNotificationInternal(
                 n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */);
     }
 
+    private NotificationVisibility obtainVisibility(String key) {
+        final int rank = mNotificationData.getRank(key);
+        final int count = mNotificationData.getActiveNotifications().size();
+        NotificationVisibility.NotificationLocation location =
+                NotificationLogger.getNotificationLocation(getNotificationData().get(key));
+        return NotificationVisibility.obtain(key, rank, count, true, location);
+    }
+
     private void abortExistingInflation(String key) {
         if (mPendingNotifications.containsKey(key)) {
             NotificationEntry entry = mPendingNotifications.get(key);
@@ -226,8 +229,8 @@
 
     @Override
     public void removeNotification(String key, NotificationListenerService.RankingMap ranking) {
-        removeNotificationInternal(
-                key, ranking, null, false /* forceRemove */, false /* removedByUser */);
+        removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
+                false /* removedByUser */);
     }
 
     private void removeNotificationInternal(
@@ -245,7 +248,8 @@
         if (entry != null) {
             // If a manager needs to keep the notification around for whatever reason, we
             // keep the notification
-            if (!forceRemove) {
+            boolean entryDismissed = entry.isRowDismissed();
+            if (!forceRemove && !entryDismissed) {
                 for (NotificationLifetimeExtender extender : mNotificationLifetimeExtenders) {
                     if (extender.shouldExtendLifetime(entry)) {
                         mLatestRankingMap = ranking;
@@ -272,6 +276,7 @@
                 mNotificationData.remove(key, ranking);
                 updateNotifications();
                 Dependency.get(LeakDetector.class).trackGarbage(entry);
+                removedByUser |= entryDismissed;
 
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onEntryRemoved(entry, visibility, removedByUser);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 5cd1210..f1373d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -543,14 +543,6 @@
         return row == null || row.isRemoved();
     }
 
-    /**
-     * @return {@code true} if the row is null or dismissed
-     */
-    public boolean isDismissed() {
-        //TODO: recycling
-        return row == null || row.isDismissed();
-    }
-
     public boolean isRowPinned() {
         return row != null && row.isPinned();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c389082..b540fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -42,6 +42,7 @@
 import android.annotation.SuppressLint;
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Point;
@@ -59,6 +60,8 @@
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
@@ -355,6 +358,46 @@
         }
     };
 
+    private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() {
+        @Override
+        public void onListenerRegistered(IPinnedStackController controller) {
+        }
+
+        @Override
+        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+            post(() -> {
+                // When the ime changes visibility, resize the edge panels to not cover the ime
+                final int width = mPrototypeController.getEdgeSensitivityWidth();
+                final int height = mContext.getDisplay().getHeight() - imeHeight
+                        - getResources().getDimensionPixelOffset(R.dimen.status_bar_height);
+                if (mLeftEdgePanel != null) {
+                    mLeftEdgePanel.setDimensions(width, height);
+                }
+                if (mRightEdgePanel != null) {
+                    mRightEdgePanel.setDimensions(width, height);
+                }
+            });
+        }
+
+        @Override
+        public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        }
+
+        @Override
+        public void onMinimizedStateChanged(boolean isMinimized) {
+        }
+
+        @Override
+        public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+                Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+                int displayRotation) {
+        }
+
+        @Override
+        public void onActionsChanged(ParceledListSlice actions) {
+        }
+    };
+
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -1296,13 +1339,19 @@
             int height = mPrototypeController.getEdgeSensitivityHeight();
             // Explicitly left and right, not start and end as this is device relative.
             mLeftEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
-                    Gravity.LEFT | Gravity.BOTTOM);
+                    Gravity.LEFT | Gravity.TOP);
             mRightEdgePanel = NavigationBarEdgePanel.create(getContext(), width, height,
-                    Gravity.RIGHT | Gravity.BOTTOM);
+                    Gravity.RIGHT | Gravity.TOP);
             mLeftEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
             mRightEdgePanel.setOnTouchListener(mEdgePanelTouchListener);
             wm.addView(mLeftEdgePanel, mLeftEdgePanel.getLayoutParams());
             wm.addView(mRightEdgePanel, mRightEdgePanel.getLayoutParams());
+
+            try {
+                WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register pinned stack listener", e);
+            }
         }
     }
 
@@ -1327,6 +1376,7 @@
         if (mRightEdgePanel != null) {
             wm.removeView(mRightEdgePanel);
         }
+        WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
     }
 
     private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 8714a51..265fa2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -421,6 +421,8 @@
                         interpolatedFract);
                 mCurrentInFrontAlpha = 0;
             }
+            mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
+                    mState.getBehindTint(), interpolatedFract);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 73ee0bd..b9afea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -22,11 +22,14 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -47,12 +50,15 @@
 @TestableLooper.RunWithLooper
 public class AppOpsControllerTest extends SysuiTestCase {
     private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-    private static final int TEST_UID_OTHER = 500000;
+    private static final int TEST_UID = UserHandle.getUid(0, 0);
+    private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0);
+    private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0);
 
     @Mock
     private AppOpsManager mAppOpsManager;
     @Mock
+    private PackageManager mPackageManager;
+    @Mock
     private AppOpsController.Callback mCallback;
     @Mock
     private AppOpsControllerImpl.H mMockHandler;
@@ -65,6 +71,18 @@
 
         getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
 
+        // All permissions of TEST_UID and TEST_UID_OTHER are user sensitive. None of
+        // TEST_UID_NON_USER_SENSITIVE are user sensitive.
+        getContext().setMockPackageManager(mPackageManager);
+        when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+                eq(UserHandle.getUserHandleForUid(TEST_UID)))).thenReturn(
+                PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
+        when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+                eq(UserHandle.getUserHandleForUid(TEST_UID_OTHER)))).thenReturn(
+                PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED);
+        when(mPackageManager.getPermissionFlags(anyString(), anyString(),
+                eq(UserHandle.getUserHandleForUid(TEST_UID_NON_USER_SENSITIVE)))).thenReturn(0);
+
         mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER));
     }
 
@@ -157,6 +175,14 @@
     }
 
     @Test
+    public void nonUserSensitiveOpsAreIgnored() {
+        mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID_NON_USER_SENSITIVE, TEST_PACKAGE_NAME, true);
+        assertEquals(0, mController.getActiveAppOpsForUser(
+                UserHandle.getUserId(TEST_UID_NON_USER_SENSITIVE)).size());
+    }
+
+    @Test
     public void opNotedScheduledForRemoval() {
         mController.setBGHandler(mMockHandler);
         mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 0fd7834..42c221a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -20,10 +20,13 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.IActivityManager;
+import android.app.PendingIntent;
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -83,6 +86,9 @@
     @Mock
     private BubbleController.BubbleExpandListener mBubbleExpandListener;
 
+    @Mock
+    private PendingIntent mDeleteIntent;
+
     private BubbleData mBubbleData;
 
     @Before
@@ -98,9 +104,9 @@
 
         // Need notifications for bubbles
         mNotificationTestHelper = new NotificationTestHelper(mContext);
-        mRow = mNotificationTestHelper.createBubble();
-        mRow2 = mNotificationTestHelper.createBubble();
-        mNoChannelRow = mNotificationTestHelper.createBubble();
+        mRow = mNotificationTestHelper.createBubble(mDeleteIntent);
+        mRow2 = mNotificationTestHelper.createBubble(mDeleteIntent);
+        mNoChannelRow = mNotificationTestHelper.createBubble(mDeleteIntent);
 
         // Return non-null notification data from the NEM
         when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData);
@@ -141,11 +147,10 @@
 
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true);
 
-        mBubbleController.removeBubble(mRow.getEntry().key);
+        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         assertTrue(mRow.getEntry().isBubbleDismissed());
         verify(mNotificationEntryManager).updateNotifications();
-
         verify(mBubbleStateChangeListener).onHasBubblesChanged(false);
     }
 
@@ -155,7 +160,7 @@
         mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
         assertTrue(mBubbleController.hasBubbles());
 
-        mBubbleController.dismissStack();
+        mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
         assertFalse(mStatusBarWindowController.getBubblesShowing());
         verify(mNotificationEntryManager).updateNotifications();
         assertTrue(mRow.getEntry().isBubbleDismissed());
@@ -271,7 +276,8 @@
         assertFalse(mRow2.getEntry().showInShadeWhenBubble());
 
         // Dismiss currently expanded
-        mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey());
+        mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
+                BubbleController.DISMISS_USER_GESTURE);
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow2.getEntry().key);
 
         // Make sure next bubble is selected
@@ -279,7 +285,8 @@
         verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getEntry().key);
 
         // Dismiss that one
-        mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey());
+        mBubbleController.removeBubble(stackView.getExpandedBubbleView().getKey(),
+                BubbleController.DISMISS_USER_GESTURE);
 
         // Make sure state changes and collapse happens
         verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getEntry().key);
@@ -299,6 +306,28 @@
         assertTrue(mRow.getEntry().showInShadeWhenBubble());
     }
 
+    @Test
+    public void testDeleteIntent_removeBubble_aged() throws PendingIntent.CanceledException {
+        mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_AGED);
+        verify(mDeleteIntent, never()).send();
+    }
+
+    @Test
+    public void testDeleteIntent_removeBubble_user() throws PendingIntent.CanceledException {
+        mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+        mBubbleController.removeBubble(mRow.getEntry().key, BubbleController.DISMISS_USER_GESTURE);
+        verify(mDeleteIntent, times(1)).send();
+    }
+
+    @Test
+    public void testDeleteIntent_dismissStack() throws PendingIntent.CanceledException {
+        mBubbleController.updateBubble(mRow.getEntry(), true /* updatePosition */);
+        mBubbleController.updateBubble(mRow2.getEntry(), true /* updatePosition */);
+        mBubbleController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
+        verify(mDeleteIntent, times(2)).send();
+    }
+
     static class TestableBubbleController extends BubbleController {
 
         TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
index cef78db..de15505 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -23,6 +23,7 @@
 import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.app.Notification;
+import android.app.Notification.BubbleMetadata;
 import android.app.NotificationChannel;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -152,8 +153,18 @@
      * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
      */
     public ExpandableNotificationRow createBubble() throws Exception {
+        return createBubble(null);
+    }
+
+    /**
+     * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble.
+     *
+     * @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent}
+     */
+    public ExpandableNotificationRow createBubble(@Nullable PendingIntent deleteIntent)
+            throws Exception {
         Notification n = createNotification(false /* isGroupSummary */,
-                null /* groupKey */, true /* isBubble */);
+                null /* groupKey */, true /* isBubble */, deleteIntent);
         return generateRow(n, PKG, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH);
     }
 
@@ -196,7 +207,8 @@
      * @return a notification that is in the group specified or standalone if unspecified
      */
     private Notification createNotification(boolean isGroupSummary, @Nullable String groupKey) {
-        return createNotification(isGroupSummary, groupKey, false /* isBubble */);
+        return createNotification(isGroupSummary, groupKey, false /* isBubble */,
+                null /* bubbleDeleteIntent */);
     }
 
     /**
@@ -208,7 +220,8 @@
      * @return a notification that is in the group specified or standalone if unspecified
      */
     private Notification createNotification(boolean isGroupSummary,
-            @Nullable String groupKey, boolean isBubble) {
+            @Nullable String groupKey, boolean isBubble,
+            @Nullable PendingIntent bubbleDeleteIntent) {
         Notification publicVersion = new Notification.Builder(mContext).setSmallIcon(
                 R.drawable.ic_person)
                 .setCustomContentView(new RemoteViews(mContext.getPackageName(),
@@ -227,7 +240,8 @@
             notificationBuilder.setGroup(groupKey);
         }
         if (isBubble) {
-            notificationBuilder.setBubbleMetadata(makeBubbleMetadata());
+            BubbleMetadata metadata = makeBubbleMetadata(bubbleDeleteIntent);
+            notificationBuilder.setBubbleMetadata(metadata);
         }
         return notificationBuilder.build();
     }
@@ -291,11 +305,13 @@
         return row;
     }
 
-    private Notification.BubbleMetadata makeBubbleMetadata() {
+    private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) {
         Intent target = new Intent(mContext, BubblesTestActivity.class);
         PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, 0);
-        return new Notification.BubbleMetadata.Builder()
+
+        return new BubbleMetadata.Builder()
                 .setIntent(bubbleIntent)
+                .setDeleteIntent(deleteIntent)
                 .setTitle("bubble title")
                 .setIcon(Icon.createWithResource(mContext, 1))
                 .setDesiredHeight(314)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 5543744..c8005dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -347,7 +347,7 @@
 
         verify(mPresenter).updateNotificationViews();
         verify(mEntryListener).onEntryRemoved(
-                mEntry, null, false /* removedByUser */);
+                eq(mEntry), any(), eq(false) /* removedByUser */);
         verify(mRow).setRemoved();
 
         assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
@@ -360,7 +360,7 @@
         mEntryManager.removeNotification("not_a_real_key", mRankingMap);
 
         verify(mEntryListener, never()).onEntryRemoved(
-                mEntry, null, false /* removedByUser */);
+                eq(mEntry), any(), eq(false) /* removedByUser */);
     }
 
     @Test
@@ -373,7 +373,7 @@
         mEntryManager.removeNotification(mSbn.getKey(), mRankingMap);
 
         verify(mEntryListener, never()).onEntryRemoved(
-                mEntry, null, false /* removedByUser */);
+                eq(mEntry), any(), eq(false /* removedByUser */));
     }
 
     @Test
@@ -455,7 +455,7 @@
         verify(extender).setShouldManageLifetime(mEntry, true);
         // THEN the notification is retained
         assertNotNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
-        verify(mEntryListener, never()).onEntryRemoved(mEntry, null, false);
+        verify(mEntryListener, never()).onEntryRemoved(eq(mEntry), any(), eq(false));
     }
 
     @Test
@@ -474,7 +474,7 @@
 
         // THEN the notification is removed
         assertNull(mEntryManager.getNotificationData().get(mSbn.getKey()));
-        verify(mEntryListener).onEntryRemoved(mEntry, null, false);
+        verify(mEntryListener).onEntryRemoved(eq(mEntry), any(), eq(false));
     }
 
     @Test
diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicAndroidService.java
index 12a3f02..8488941 100644
--- a/services/core/java/com/android/server/DynamicAndroidService.java
+++ b/services/core/java/com/android/server/DynamicAndroidService.java
@@ -118,7 +118,9 @@
         if (gsiService.isGsiRunning()) {
             return gsiService.disableGsiInstall();
         } else {
-            return gsiService.setGsiBootable() == 0;
+            final int status = gsiService.getGsiBootStatus();
+            final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT);
+            return gsiService.setGsiBootable(singleBoot) == 0;
         }
     }
 
@@ -129,6 +131,6 @@
 
     @Override
     public boolean commit() throws RemoteException {
-        return getGsiService().setGsiBootable() == 0;
+        return getGsiService().setGsiBootable(true) == 0;
     }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index bbd51ad..c2a0611 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -3210,18 +3210,6 @@
                 continue;
             }
 
-            if (!reportLocationAccessNoThrow(
-                    receiver.mCallerIdentity.mPid,
-                    receiver.mCallerIdentity.mUid,
-                    receiver.mCallerIdentity.mPackageName,
-                    receiver.mAllowedResolutionLevel)) {
-                if (D) {
-                    Log.d(TAG, "skipping loc update for no op app: " +
-                            receiver.mCallerIdentity.mPackageName);
-                }
-                continue;
-            }
-
             Location notifyLocation;
             if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
                 notifyLocation = coarseLocation;  // use coarse location
@@ -3238,6 +3226,20 @@
                     } else {
                         lastLoc.set(notifyLocation);
                     }
+                    // Report location access before delivering location to the client. This will
+                    // note location delivery to appOps, so it should be called only when a
+                    // location is really being delivered to the client.
+                    if (!reportLocationAccessNoThrow(
+                            receiver.mCallerIdentity.mPid,
+                            receiver.mCallerIdentity.mUid,
+                            receiver.mCallerIdentity.mPackageName,
+                            receiver.mAllowedResolutionLevel)) {
+                        if (D) {
+                            Log.d(TAG, "skipping loc update for no op app: "
+                                    + receiver.mCallerIdentity.mPackageName);
+                        }
+                        continue;
+                    }
                     if (!receiver.callLocationChangedLocked(notifyLocation)) {
                         Slog.w(TAG, "RemoteException calling onLocationChanged on "
                                 + receiver);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index dc394d0..5582ad7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2512,6 +2512,10 @@
                 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
             }
         }
+
+        // IPv6 link local should be activated always.
+        modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
+                new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
new file mode 100644
index 0000000..e64ab78
--- /dev/null
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.INetd;
+import android.net.ITestNetworkManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
+import android.net.StringNetworkSpecifier;
+import android.net.TestNetworkInterface;
+import android.net.util.NetdService;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.UncheckedIOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** @hide */
+class TestNetworkService extends ITestNetworkManager.Stub {
+    @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
+    @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
+    @NonNull private static final String TEST_TUN_PREFIX = "testtun";
+    @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
+
+    @NonNull private final Context mContext;
+    @NonNull private final INetworkManagementService mNMS;
+    @NonNull private final INetd mNetd;
+
+    @NonNull private final HandlerThread mHandlerThread;
+    @NonNull private final Handler mHandler;
+
+    // Native method stubs
+    private static native int jniCreateTun(@NonNull String iface);
+
+    @VisibleForTesting
+    protected TestNetworkService(
+            @NonNull Context context, @NonNull INetworkManagementService netManager) {
+        mHandlerThread = new HandlerThread("TestNetworkServiceThread");
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+
+        mContext = checkNotNull(context, "missing Context");
+        mNMS = checkNotNull(netManager, "missing INetworkManagementService");
+        mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance");
+    }
+
+    /**
+     * Create a TUN interface with the given interface name and link addresses
+     *
+     * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
+     * TUN interface.
+     */
+    @Override
+    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+        enforceTestNetworkPermissions(mContext);
+
+        checkNotNull(linkAddrs, "missing linkAddrs");
+
+        String iface = TEST_TUN_PREFIX + sTestTunIndex.getAndIncrement();
+        return Binder.withCleanCallingIdentity(
+                () -> {
+                    try {
+                        ParcelFileDescriptor tunIntf =
+                                ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
+                        for (LinkAddress addr : linkAddrs) {
+                            mNetd.interfaceAddAddress(
+                                    iface,
+                                    addr.getAddress().getHostAddress(),
+                                    addr.getPrefixLength());
+                        }
+
+                        return new TestNetworkInterface(tunIntf, iface);
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                });
+    }
+
+    // Tracker for TestNetworkAgents
+    @GuardedBy("mTestNetworkTracker")
+    @NonNull
+    private final SparseArray<TestNetworkAgent> mTestNetworkTracker = new SparseArray<>();
+
+    public class TestNetworkAgent extends NetworkAgent implements IBinder.DeathRecipient {
+        private static final int NETWORK_SCORE = 1; // Use a low, non-zero score.
+
+        private final int mUid;
+        @NonNull private final NetworkInfo mNi;
+        @NonNull private final NetworkCapabilities mNc;
+        @NonNull private final LinkProperties mLp;
+
+        @GuardedBy("mBinderLock")
+        @NonNull
+        private IBinder mBinder;
+
+        @NonNull private final Object mBinderLock = new Object();
+
+        private TestNetworkAgent(
+                @NonNull Looper looper,
+                @NonNull Context context,
+                @NonNull NetworkInfo ni,
+                @NonNull NetworkCapabilities nc,
+                @NonNull LinkProperties lp,
+                int uid,
+                @NonNull IBinder binder)
+                throws RemoteException {
+            super(looper, context, TEST_NETWORK_TYPE, ni, nc, lp, NETWORK_SCORE);
+
+            mUid = uid;
+            mNi = ni;
+            mNc = nc;
+            mLp = lp;
+
+            synchronized (mBinderLock) {
+                mBinder = binder; // Binder null-checks in create()
+
+                try {
+                    mBinder.linkToDeath(this, 0);
+                } catch (RemoteException e) {
+                    binderDied();
+                    throw e; // Abort, signal failure up the stack.
+                }
+            }
+        }
+
+        /**
+         * If the Binder object dies, this function is called to free the resources of this
+         * TestNetworkAgent
+         */
+        @Override
+        public void binderDied() {
+            teardown();
+        }
+
+        @Override
+        protected void unwanted() {
+            teardown();
+        }
+
+        private void teardown() {
+            mNi.setDetailedState(DetailedState.DISCONNECTED, null, null);
+            mNi.setIsAvailable(false);
+            sendNetworkInfo(mNi);
+
+            // Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than
+            // once (otherwise it could throw an exception)
+            synchronized (mBinderLock) {
+                // If mBinder is null, this Test Network has already been cleaned up.
+                if (mBinder == null) return;
+                mBinder.unlinkToDeath(this, 0);
+                mBinder = null;
+            }
+
+            // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
+            // resources, even for binder death or unwanted calls.
+            synchronized (mTestNetworkTracker) {
+                mTestNetworkTracker.remove(netId);
+            }
+        }
+    }
+
+    private TestNetworkAgent registerTestNetworkAgent(
+            @NonNull Looper looper,
+            @NonNull Context context,
+            @NonNull String iface,
+            int callingUid,
+            @NonNull IBinder binder)
+            throws RemoteException, SocketException {
+        checkNotNull(looper, "missing Looper");
+        checkNotNull(context, "missing Context");
+        // iface and binder validity checked by caller
+
+        // Build network info with special testing type
+        NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_TEST, 0, TEST_NETWORK_TYPE, "");
+        ni.setDetailedState(DetailedState.CONNECTED, null, null);
+        ni.setIsAvailable(true);
+
+        // Build narrow set of NetworkCapabilities, useful only for testing
+        NetworkCapabilities nc = new NetworkCapabilities();
+        nc.clearAll(); // Remove default capabilities.
+        nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+        nc.setNetworkSpecifier(new StringNetworkSpecifier(iface));
+
+        // Build LinkProperties
+        LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(iface);
+
+        // Find the currently assigned addresses, and add them to LinkProperties
+        boolean allowIPv4 = false, allowIPv6 = false;
+        NetworkInterface netIntf = NetworkInterface.getByName(iface);
+        checkNotNull(netIntf, "No such network interface found: " + netIntf);
+
+        for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
+            lp.addLinkAddress(
+                    new LinkAddress(intfAddr.getAddress(), intfAddr.getNetworkPrefixLength()));
+
+            if (intfAddr.getAddress() instanceof Inet6Address) {
+                allowIPv6 |= !intfAddr.getAddress().isLinkLocalAddress();
+            } else if (intfAddr.getAddress() instanceof Inet4Address) {
+                allowIPv4 = true;
+            }
+        }
+
+        // Add global routes (but as non-default, non-internet providing network)
+        if (allowIPv4) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null, iface));
+        }
+        if (allowIPv6) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
+        }
+
+        return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder);
+    }
+
+    /**
+     * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS
+     * permission.
+     *
+     * <p>This method provides a Network that is useful only for testing.
+     */
+    @Override
+    public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+        enforceTestNetworkPermissions(mContext);
+
+        checkNotNull(iface, "missing Iface");
+        checkNotNull(binder, "missing IBinder");
+
+        if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX)
+                || iface.startsWith(TEST_TUN_PREFIX))) {
+            throw new IllegalArgumentException(
+                    "Cannot create network for non ipsec, non-testtun interface");
+        }
+
+        // Setup needs to be done with NETWORK_STACK privileges.
+        int callingUid = Binder.getCallingUid();
+        Binder.withCleanCallingIdentity(
+                () -> {
+                    try {
+                        mNMS.setInterfaceUp(iface);
+
+                        // Synchronize all accesses to mTestNetworkTracker to prevent the case
+                        // where:
+                        // 1. TestNetworkAgent successfully binds to death of binder
+                        // 2. Before it is added to the mTestNetworkTracker, binder dies,
+                        // binderDied() is called (on a different thread)
+                        // 3. This thread is pre-empted, put() is called after remove()
+                        synchronized (mTestNetworkTracker) {
+                            TestNetworkAgent agent =
+                                    registerTestNetworkAgent(
+                                            mHandler.getLooper(),
+                                            mContext,
+                                            iface,
+                                            callingUid,
+                                            binder);
+
+                            mTestNetworkTracker.put(agent.netId, agent);
+                        }
+                    } catch (SocketException e) {
+                        throw new UncheckedIOException(e);
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                });
+    }
+
+    /** Teardown a test network */
+    @Override
+    public void teardownTestNetwork(int netId) {
+        enforceTestNetworkPermissions(mContext);
+
+        TestNetworkAgent agent;
+        synchronized (mTestNetworkTracker) {
+            agent = mTestNetworkTracker.get(netId);
+        }
+
+        if (agent == null) {
+            return; // Already torn down
+        } else if (agent.mUid != Binder.getCallingUid()) {
+            throw new SecurityException("Attempted to modify other user's test networks");
+        }
+
+        // Safe to be called multiple times.
+        agent.teardown();
+    }
+
+    // STOPSHIP: Change this back to android.Manifest.permission.MANAGE_TEST_NETWORKS
+    private static final String PERMISSION_NAME = "dummy";
+
+    public static void enforceTestNetworkPermissions(@NonNull Context context) {
+        // STOPSHIP: Re-enable these checks. Disabled until adoptShellPermissionIdentity() can be
+        //           called from CTS test code.
+        if (false) {
+            context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService");
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 59fffb4..8005dda 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1842,6 +1842,7 @@
         config.interfaze = iface;
         config.session = profile.name;
         config.isMetered = false;
+        config.proxyInfo = profile.proxy;
 
         config.addLegacyRoutes(profile.routes);
         if (!profile.dnsServers.isEmpty()) {
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 500c388..a2515c8 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -29,6 +29,8 @@
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -44,6 +46,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -66,6 +69,7 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.view.inputmethod.InputMethodSystemProperty;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IMultiClientInputMethod;
 import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
@@ -73,6 +77,8 @@
 import com.android.internal.inputmethod.StartInputFlags;
 import com.android.internal.inputmethod.StartInputReason;
 import com.android.internal.inputmethod.UnbindReason;
+import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
@@ -96,8 +102,15 @@
  * we can switch the implementation at the boot time.</p>
  */
 public final class MultiClientInputMethodManagerService {
-    static final String TAG = "MultiClientInputMethodManagerService";
-    static final boolean DEBUG = false;
+    private static final String TAG = "MultiClientInputMethodManagerService";
+    private static final boolean DEBUG = false;
+
+    private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE =
+            "config_perDisplayFocusEnabled is not true.";
+
+    private static final String PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG =
+            "Consider rebuilding the system image after enabling config_perDisplayFocusEnabled to "
+                    + "make IME focus compatible with multi-client IME mode.";
 
     private static final long RECONNECT_DELAY_MSEC = 1000;
 
@@ -465,8 +478,33 @@
                             onPackageAdded(intent);
                         }
                     }, filter, null, mHandler);
+                    break;
                 }
-                break;
+                case SystemService.PHASE_BOOT_COMPLETED: {
+                    final boolean perDisplayFocusEnabled = mContext.getResources().getBoolean(
+                            com.android.internal.R.bool.config_perDisplayFocusEnabled);
+                    if (!perDisplayFocusEnabled) {
+                        final Bundle extras = new Bundle();
+                        extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
+                        mContext.getSystemService(NotificationManager.class).notifyAsUser(TAG,
+                                SystemMessageProto.SystemMessage.NOTE_SELECT_INPUT_METHOD,
+                                new Notification.Builder(mContext,
+                                        SystemNotificationChannels.VIRTUAL_KEYBOARD)
+                                        .setContentTitle(PER_DISPLAY_FOCUS_DISABLED_WARNING_TITLE)
+                                        .setStyle(new Notification.BigTextStyle()
+                                                .bigText(PER_DISPLAY_FOCUS_DISABLED_WARNING_MSG))
+                                        .setSmallIcon(R.drawable.ic_notification_ime_default)
+                                        .setWhen(0)
+                                        .setOngoing(true)
+                                        .setLocalOnly(true)
+                                        .addExtras(extras)
+                                        .setCategory(Notification.CATEGORY_SYSTEM)
+                                        .setColor(mContext.getColor(
+                                                R.color.system_notification_accent_color))
+                                        .build(), UserHandle.ALL);
+                    }
+                    break;
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/inputmethod/multi-client-ime.md b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
index 3021d2f..ba92cd2 100644
--- a/services/core/java/com/android/server/inputmethod/multi-client-ime.md
+++ b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
@@ -39,7 +39,9 @@
 
 ## How to test
 
-On AOSP-based development devices (e.g. phones) where `android.os.Build.IS_DEBUGGABLE` returns `true` and you can have root access, you can enable multi-client IME feature by setting a valid component name that supports multi-client IME protocol to the system property `persist.debug.multi_client_ime`. Reboot is required for this to take effect.
+For multi-client IME to properly work, an internal boolean resource `com.android.internal.R.bool.config_perDisplayFocusEnabled` needs to be `true`. Since this value cannot be overridden at the run time, you may need to rebuild the system image to enable per-display focus mode.
+
+As for multi-client IME mode itself, you can enable multi-client IME mode just by setting a valid component name that supports multi-client IME protocol to the system property `persist.debug.multi_client_ime`, as long as `android.os.Build.IS_DEBUGGABLE` returns `true` and you can have root access. Reboot is required for this to take effect.
 
 ```shell
 # Build and install a sample multi-client IME
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 2e91f99..28ae6a4 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,12 +1,11 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
 jsharkey@android.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
-silberst@google.com
 sudheersai@google.com
 yamasani@google.com
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 5c7b287..050a079 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -38,6 +38,7 @@
         "com_android_server_SerialService.cpp",
         "com_android_server_storage_AppFuseBridge.cpp",
         "com_android_server_SystemServer.cpp",
+        "com_android_server_TestNetworkService.cpp",
         "com_android_server_tv_TvUinputBridge.cpp",
         "com_android_server_tv_TvInputHal.cpp",
         "com_android_server_vr_VrManagerService.cpp",
diff --git a/services/core/jni/com_android_server_TestNetworkService.cpp b/services/core/jni/com_android_server_TestNetworkService.cpp
new file mode 100644
index 0000000..b90ff23
--- /dev/null
+++ b/services/core/jni/com_android_server_TestNetworkService.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+
+#define LOG_TAG "TestNetworkServiceJni"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/ipv6_route.h>
+#include <linux/route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+
+#include "netutils/ifc.h"
+
+#include "jni.h"
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+namespace android {
+
+//------------------------------------------------------------------------------
+
+static void throwException(JNIEnv* env, int error, const char* action, const char* iface) {
+    const std::string& msg =
+        android::base::StringPrintf("Error %s %s: %s", action, iface, strerror(error));
+
+    jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
+}
+
+static int createTunInterface(JNIEnv* env, const char* iface) {
+    base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
+    ifreq ifr{};
+
+    // Allocate interface.
+    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+    strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+    if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
+        throwException(env, errno, "allocating", ifr.ifr_name);
+        return -1;
+    }
+
+    // Activate interface using an unconnected datagram socket.
+    base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+    ifr.ifr_flags = IFF_UP;
+
+    if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+        throwException(env, errno, "activating", ifr.ifr_name);
+        return -1;
+    }
+
+    return tun.release();
+}
+
+//------------------------------------------------------------------------------
+
+static jint create(JNIEnv* env, jobject /* thiz */, jstring jIface) {
+    ScopedUtfChars iface(env, jIface);
+    if (!iface.c_str()) {
+        jniThrowNullPointerException(env, "iface");
+        return -1;
+    }
+
+    int tun = createTunInterface(env, iface.c_str());
+
+    // Any exceptions will be thrown from the createTunInterface call
+    return tun;
+}
+
+//------------------------------------------------------------------------------
+
+static const JNINativeMethod gMethods[] = {
+    {"jniCreateTun", "(Ljava/lang/String;)I", (void*)create},
+};
+
+int register_android_server_TestNetworkService(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods,
+                                    NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 6e31aed..5ffed03 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -41,6 +41,7 @@
 int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
 int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
+int register_android_server_TestNetworkService(JNIEnv* env);
 int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*);
 int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
 int register_android_server_tv_TvUinputBridge(JNIEnv* env);
@@ -85,6 +86,7 @@
     register_android_server_location_GnssLocationProvider(env);
     register_android_server_connectivity_Vpn(env);
     register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
+    register_android_server_TestNetworkService(env);
     register_android_server_devicepolicy_CryptoTestHelper(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_BatteryStatsService(env);
diff --git a/services/net/OWNERS b/services/net/OWNERS
index 7311eee..d3836d4 100644
--- a/services/net/OWNERS
+++ b/services/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 830dbbe..eed01ae 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -289,7 +289,8 @@
     private void requestConnector(@NonNull NetworkStackCallback request) {
         // TODO: PID check.
         final int caller = Binder.getCallingUid();
-        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
+                && !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
             // Don't even attempt to obtain the connector and give a nice error message
             throw new SecurityException(
                     "Only the system server should try to bind to the network stack.");
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 34fc735..0e44f88 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -87,7 +87,6 @@
         return "UNKNOWN: " + state;
     }
 
-    private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
     private static final byte DOUG_ADAMS = (byte) 42;
 
     private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
@@ -557,16 +556,6 @@
                 addedPrefixes.removeAll(mLastRaParams.prefixes);
             }
 
-            if (mLastRaParams == null || mLastRaParams.prefixes.isEmpty()) {
-                // We need to be able to send unicast RAs, and clients might
-                // like to ping the default router's link-local address.  Note
-                // that we never remove the link-local route from the network
-                // until Tethering disables tethering on the interface. We
-                // only need to add the link-local prefix once, but in the
-                // event we add it more than once netd silently ignores EEXIST.
-                addedPrefixes.add(LINK_LOCAL_PREFIX);
-            }
-
             if (!addedPrefixes.isEmpty()) {
                 final ArrayList<RouteInfo> toBeAdded =
                         getLocalRoutesFor(mIfaceName, addedPrefixes);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 511b278..5262cf8 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -31,6 +31,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.carrier.CarrierService;
+import android.telecom.TelecomManager;
 import android.telephony.ims.ImsReasonInfo;
 
 import com.android.internal.telephony.ICarrierConfigLoader;
@@ -2114,6 +2115,18 @@
     public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
 
     /**
+     * Boolean flag indicating whether the carrier supports TTY.
+     * <p>
+     * Note that {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} controls availability of TTY over
+     * VoLTE; if {@link #KEY_TTY_SUPPORTED_BOOL} is disabled, then
+     * {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} is also implicitly disabled.
+     * <p>
+     * {@link TelecomManager#isTtySupported()} should be used to determine if a device supports TTY,
+     * and this carrier config key should be used to see if the current carrier supports it.
+     */
+    public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
+
+    /**
      * Indicates if the carrier supports auto-upgrading a call to RTT when receiving a call from a
      * RTT-supported device.
      * @hide
@@ -2959,6 +2972,7 @@
         sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
+        sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
         sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 223f3ef..1796034 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -22,7 +22,6 @@
 import android.hardware.radio.V1_4.CellInfo.Info;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -325,9 +324,9 @@
     }
 
     /** @hide */
-    protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) {
+    protected CellInfo(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
         this.mRegistered = ci.isRegistered;
-        this.mTimeStamp = SystemClock.elapsedRealtimeNanos();
+        this.mTimeStamp = timeStamp;
         this.mCellConnectionStatus = ci.connectionStatus;
     }
 
@@ -358,14 +357,14 @@
     }
 
     /** @hide */
-    public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) {
+    public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
         if (ci == null) return null;
         switch (ci.info.getDiscriminator()) {
-            case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci);
-            case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci);
-            case Info.hidl_discriminator.lte: return new CellInfoLte(ci);
-            case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci);
-            case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci);
+            case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci, timeStamp);
+            case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci, timeStamp);
+            case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp);
+            case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp);
+            case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp);
             default: return null;
         }
     }
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 9c38506..82bb3961 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -68,8 +68,8 @@
     }
 
     /** @hide */
-    public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma();
         mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
         mCellSignalStrengthCdma =
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 0d91f80..59fcd1e 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -64,8 +64,8 @@
     }
 
     /** @hide */
-    public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm();
         mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
         mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index deae632..08dafe1 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -71,8 +71,8 @@
     }
 
     /** @hide */
-    public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte();
         mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte);
         mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte);
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index ae43bb2..93baabf 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -65,8 +65,8 @@
     }
 
     /** @hide */
-    public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma();
         mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
         mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index d2287ea..02dbb1a 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -64,8 +64,8 @@
     }
 
     /** @hide */
-    public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma();
         mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
         mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
diff --git a/telephony/java/android/telephony/MbmsGroupCallSession.java b/telephony/java/android/telephony/MbmsGroupCallSession.java
index 269cda1..f1be31f 100644
--- a/telephony/java/android/telephony/MbmsGroupCallSession.java
+++ b/telephony/java/android/telephony/MbmsGroupCallSession.java
@@ -141,7 +141,7 @@
      * Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
      * See {@link #create(Context, int, Executor, MbmsGroupCallSessionCallback)}.
      */
-    public static MbmsGroupCallSession create(@NonNull Context context,
+    public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
             @NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
         return create(context, SubscriptionManager.getDefaultSubscriptionId(), executor, callback);
     }
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index fb6f39d..245f5b3 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -425,14 +425,14 @@
     /**
      * @return The MCC, as a string.
      */
-    public String getMccString() {
+    public @Nullable String getMccString() {
         return this.mMcc;
     }
 
     /**
      * @return The MNC, as a string.
      */
-    public String getMncString() {
+    public @Nullable String getMncString() {
         return this.mMnc;
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8edc5b4..d9a37c6 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2706,7 +2706,8 @@
      *  1) Even if it's active, it will be dormant most of the time. The modem will not try
      *     to scan or camp until it knows an available network is nearby to save power.
      *  2) Telephony relies on system app or carrier input to notify nearby available networks.
-     *     See {@link TelephonyManager#updateAvailableNetworks(List)} for more information.
+     *     See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)}
+     *     for more information.
      *  3) In multi-SIM devices, when the network is nearby and camped, system may automatically
      *     switch internet data between it and default data subscription, based on carrier
      *     recommendation and its signal strength and metered-ness, etc.
@@ -2938,7 +2939,7 @@
     }
 
     /**
-     * Enabled or disable a subscription. This is currently used in the settings page.
+     * Enables or disables a subscription. This is currently used in the settings page.
      *
      * <p>
      * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index dd58f31..beba14f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -84,6 +84,7 @@
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.RILConstants;
@@ -10190,6 +10191,41 @@
      */
     public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
+            UPDATE_AVAILABLE_NETWORKS_SUCCESS,
+            UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
+            UPDATE_AVAILABLE_NETWORKS_ABORTED,
+            UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
+            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+    public @interface UpdateAvailableNetworksResult {}
+
+    /**
+     * No error. Operation succeeded.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0;
+
+    /**
+     * There is a unknown failure happened.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1;
+
+    /**
+     * The request is aborted.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2;
+
+    /**
+     * The parameter passed in is invalid.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3;
+
+    /**
+     * No carrier privilege.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
+
     /**
      * Set preferred opportunistic data subscription id.
      *
@@ -10269,31 +10305,49 @@
     /**
      * Update availability of a list of networks in the current location.
      *
-     * This api should be called to inform OpportunisticNetwork Service about the availability
-     * of a network at the current location. This information will be used by OpportunisticNetwork
-     * service to decide to attach to the network opportunistically. If an empty list is passed,
-     * it is assumed that no network is available.
+     * This api should be called by opportunistic network selection app to inform
+     * OpportunisticNetwork Service about the availability of a network at the current location.
+     * This information will be used by OpportunisticNetwork service to decide to attach to the
+     * network opportunistically.
+     * If an empty list is passed, it is assumed that no network is available.
      * Requires that the calling app has carrier privileges on both primary and
      * secondary subscriptions (see {@link #hasCarrierPrivileges}), or has permission
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      * @param availableNetworks is a list of available network information.
-     * @return true if request is accepted
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
      *
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    public boolean updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks) {
+    public void updateAvailableNetworks(@NonNull List<AvailableNetworkInfo> availableNetworks,
+            @Nullable @CallbackExecutor Executor executor,
+            @UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
-        boolean ret = false;
         try {
             IOns iOpportunisticNetworkService = getIOns();
-            if (iOpportunisticNetworkService != null && availableNetworks != null) {
-                ret = iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks,
-                        pkgForDebug);
+            if (iOpportunisticNetworkService == null || availableNetworks == null) {
+                Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                    callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+                }));
+                return;
             }
+            IUpdateAvailableNetworksCallback callbackStub =
+                    new IUpdateAvailableNetworksCallback.Stub() {
+                        @Override
+                        public void onComplete(int result) {
+                            if (executor == null || callback == null) {
+                                return;
+                            }
+                            Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                                callback.accept(result);
+                            }));
+                        }
+                    };
+            iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks, callbackStub,
+                    pkgForDebug);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex);
         }
-        return ret;
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 0364477..2c48b65 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -19,6 +19,7 @@
 import android.telephony.AvailableNetworkInfo;
 
 import com.android.internal.telephony.ISetOpportunisticDataCallback;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 
 interface IOns {
 
@@ -97,9 +98,9 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      *  @param availableNetworks is a list of available network information.
      *  @param callingPackage caller's package name
-     *  @return true if request is accepted
+     *  @param callback callback upon request completion.
      *
      */
-    boolean updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
-            String callingPackage);
+    void updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
+            IUpdateAvailableNetworksCallback callbackStub, String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
new file mode 100644
index 0000000..8fe086ce
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 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.internal.telephony;
+
+/**
+ * Callback to provide asynchronous result of updateAvailableNetworks.
+ * @hide
+ */
+oneway interface IUpdateAvailableNetworksCallback {
+    void onComplete(int result);
+}
diff --git a/tests/AccessibilityEventsLogger/Android.bp b/tests/AccessibilityEventsLogger/Android.bp
new file mode 100644
index 0000000..ead1656
--- /dev/null
+++ b/tests/AccessibilityEventsLogger/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "AccessibilityEventsLogger",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/AccessibilityEventsLogger/Android.mk b/tests/AccessibilityEventsLogger/Android.mk
deleted file mode 100644
index 4224017..0000000
--- a/tests/AccessibilityEventsLogger/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessibilityEventsLogger
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/Android.mk b/tests/AccessoryDisplay/Android.mk
deleted file mode 100644
index 85cb309..0000000
--- a/tests/AccessoryDisplay/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AccessoryDisplay/common/Android.bp b/tests/AccessoryDisplay/common/Android.bp
new file mode 100644
index 0000000..3ce4c57
--- /dev/null
+++ b/tests/AccessoryDisplay/common/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+java_library_static {
+    name: "AccessoryDisplayCommon",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+}
diff --git a/tests/AccessoryDisplay/common/Android.mk b/tests/AccessoryDisplay/common/Android.mk
deleted file mode 100644
index 2d4de15..0000000
--- a/tests/AccessoryDisplay/common/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_MODULE := AccessoryDisplayCommon
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/AccessoryDisplay/sink/Android.bp b/tests/AccessoryDisplay/sink/Android.bp
new file mode 100644
index 0000000..4e50a81
--- /dev/null
+++ b/tests/AccessoryDisplay/sink/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "AccessoryDisplaySink",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/sink/Android.mk b/tests/AccessoryDisplay/sink/Android.mk
deleted file mode 100644
index 772ce0c..0000000
--- a/tests/AccessoryDisplay/sink/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySink
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/source/Android.bp b/tests/AccessoryDisplay/source/Android.bp
new file mode 100644
index 0000000..6d8087f
--- /dev/null
+++ b/tests/AccessoryDisplay/source/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "AccessoryDisplaySource",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/source/Android.mk b/tests/AccessoryDisplay/source/Android.mk
deleted file mode 100644
index 5d1085d..0000000
--- a/tests/AccessoryDisplay/source/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySource
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/ActivityTests/Android.bp b/tests/ActivityTests/Android.bp
new file mode 100644
index 0000000..0182862
--- /dev/null
+++ b/tests/ActivityTests/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "ActivityTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
deleted file mode 100644
index 94294f6..0000000
--- a/tests/ActivityTests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ActivityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_USE_AAPT2 := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AmSlam/Android.bp b/tests/AmSlam/Android.bp
new file mode 100644
index 0000000..a8e575a
--- /dev/null
+++ b/tests/AmSlam/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_test {
+    name: "AmSlam",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    min_sdk_version: "21",
+    java_version: "1.8",
+}
diff --git a/tests/AmSlam/Android.mk b/tests/AmSlam/Android.mk
deleted file mode 100644
index 934bae0..0000000
--- a/tests/AmSlam/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AmSlam
-
-LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Assist/Android.bp b/tests/Assist/Android.bp
new file mode 100644
index 0000000..216e751
--- /dev/null
+++ b/tests/Assist/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "Assist",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/Assist/Android.mk b/tests/Assist/Android.mk
deleted file mode 100644
index d0d3eca..0000000
--- a/tests/Assist/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := Assist
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BandwidthTests/Android.bp b/tests/BandwidthTests/Android.bp
new file mode 100644
index 0000000..523f522
--- /dev/null
+++ b/tests/BandwidthTests/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "BandwidthEnforcementTest",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+}
diff --git a/tests/BandwidthTests/Android.mk b/tests/BandwidthTests/Android.mk
deleted file mode 100644
index d00fdc6..0000000
--- a/tests/BandwidthTests/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := BandwidthEnforcementTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BatteryWaster/Android.bp b/tests/BatteryWaster/Android.bp
new file mode 100644
index 0000000..4698910
--- /dev/null
+++ b/tests/BatteryWaster/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "BatteryWaster",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/BatteryWaster/Android.mk b/tests/BatteryWaster/Android.mk
deleted file mode 100644
index fb244a8..0000000
--- a/tests/BatteryWaster/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := BatteryWaster
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BiDiTests/Android.bp b/tests/BiDiTests/Android.bp
new file mode 100644
index 0000000..c659e8c
--- /dev/null
+++ b/tests/BiDiTests/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2011 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.
+
+android_test {
+    name: "BiDiTests",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+}
diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android.mk
deleted file mode 100644
index 78cf4be..0000000
--- a/tests/BiDiTests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BiDiTests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/BrowserPowerTest/Android.bp b/tests/BrowserPowerTest/Android.bp
new file mode 100644
index 0000000..1d358cb
--- /dev/null
+++ b/tests/BrowserPowerTest/Android.bp
@@ -0,0 +1,26 @@
+// Copyright 2008, 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.
+
+android_test {
+    name: "BrowserPowerTests",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    //LOCAL_INSTRUMENTATION_FOR := browserpowertest
+}
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
deleted file mode 100644
index 0934889..0000000
--- a/tests/BrowserPowerTest/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2008, 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BrowserPowerTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-#LOCAL_INSTRUMENTATION_FOR := browserpowertest
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Camera2Tests/Android.mk b/tests/Camera2Tests/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/tests/Camera2Tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/Android.mk b/tests/Camera2Tests/SmartCamera/Android.mk
deleted file mode 100644
index 3fa8f54..0000000
--- a/tests/Camera2Tests/SmartCamera/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2013 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.
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
index 0b16b0e..a23ac38 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
@@ -15,9 +15,7 @@
 
 cc_test_library {
     name: "libsmartcamera_jni",
-
     sdk_version: "14",
-
     srcs: [
         "contrast.cpp",
         "brightness.cpp",
@@ -29,13 +27,11 @@
         "sobeloperator.cpp",
         "stats_scorer.cpp",
     ],
-
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
         "-Wno-unused-parameter",
     ],
-
     stl: "c++_static",
 }
diff --git a/tests/CameraPrewarmTest/Android.bp b/tests/CameraPrewarmTest/Android.bp
new file mode 100644
index 0000000..eaf453b
--- /dev/null
+++ b/tests/CameraPrewarmTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "CameraPrewarmTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/CameraPrewarmTest/Android.mk b/tests/CameraPrewarmTest/Android.mk
deleted file mode 100644
index e128504..0000000
--- a/tests/CameraPrewarmTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraPrewarmTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/Android.mk b/tests/CoreTests/Android.mk
deleted file mode 100644
index 8338432..0000000
--- a/tests/CoreTests/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-include $(call all-subdir-makefiles)
-
diff --git a/tests/CoreTests/android/Android.bp b/tests/CoreTests/android/Android.bp
new file mode 100644
index 0000000..24134e8
--- /dev/null
+++ b/tests/CoreTests/android/Android.bp
@@ -0,0 +1,11 @@
+android_test {
+    name: "LegacyCoreTests",
+    srcs: ["**/*.java"],
+    libs: [
+        "android.test.runner.stubs",
+        "org.apache.http.legacy",
+        "android.test.base.stubs",
+    ],
+    sdk_version: "current",
+    static_libs: ["junit"],
+}
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
deleted file mode 100644
index 04f6739..0000000
--- a/tests/CoreTests/android/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-	$(call all-subdir-java-files)
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner.stubs \
-    org.apache.http.legacy \
-    android.test.base.stubs \
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_PACKAGE_NAME := LegacyCoreTests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/Android.bp b/tests/DataIdleTest/Android.bp
new file mode 100644
index 0000000..19656ce
--- /dev/null
+++ b/tests/DataIdleTest/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "DataIdleTest",
+    platform_apis: true,
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    srcs: ["src/**/*.java"],
+    // We need to sign it to get access to the network usage history.
+    certificate: "platform",
+}
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
deleted file mode 100644
index bcf3599..0000000
--- a/tests/DataIdleTest/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := DataIdleTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# We need to sign it to get access to the network usage history.
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DozeTest/Android.bp b/tests/DozeTest/Android.bp
new file mode 100644
index 0000000..f1be029
--- /dev/null
+++ b/tests/DozeTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "DozeTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/DozeTest/Android.mk b/tests/DozeTest/Android.mk
deleted file mode 100644
index ec250ff..0000000
--- a/tests/DozeTest/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DozeTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/DpiTest/Android.bp b/tests/DpiTest/Android.bp
new file mode 100644
index 0000000..7d6a78b
--- /dev/null
+++ b/tests/DpiTest/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "DensityTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    aaptflags: [
+        "-c",
+        "120dpi,240dpi,160dpi,nodpi",
+    ],
+}
diff --git a/tests/DpiTest/Android.mk b/tests/DpiTest/Android.mk
deleted file mode 100644
index e69d082..0000000
--- a/tests/DpiTest/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DensityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/base/Android.bp b/tests/FeatureSplit/base/Android.bp
new file mode 100644
index 0000000..ab25464
--- /dev/null
+++ b/tests/FeatureSplit/base/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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.
+//
+
+android_test_helper_app {
+    name: "FeatureSplitBase",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    export_package_resources: true,
+}
diff --git a/tests/FeatureSplit/base/Android.mk b/tests/FeatureSplit/base/Android.mk
deleted file mode 100644
index 8646460..0000000
--- a/tests/FeatureSplit/base/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplitBase
-LOCAL_SDK_VERSION := current
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature1/Android.bp b/tests/FeatureSplit/feature1/Android.bp
new file mode 100644
index 0000000..1a93e84
--- /dev/null
+++ b/tests/FeatureSplit/feature1/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+android_test {
+    name: "FeatureSplit1",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: ["FeatureSplitBase"],
+    aaptflags: [
+        "--package-id",
+        "0x80",
+    ] + [
+        "--custom-package",
+        "com.android.test.split.feature.one",
+    ],
+}
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
deleted file mode 100644
index d4d2589..0000000
--- a/tests/FeatureSplit/feature1/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit1
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x80
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.one
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature2/Android.bp b/tests/FeatureSplit/feature2/Android.bp
new file mode 100644
index 0000000..a363482
--- /dev/null
+++ b/tests/FeatureSplit/feature2/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+
+android_test {
+    name: "FeatureSplit2",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: ["FeatureSplitBase"],
+    aaptflags: [
+        "--package-id",
+        "0x81",
+        "--custom-package",
+        "com.android.test.split.feature.two",
+    ],
+}
diff --git a/tests/FeatureSplit/feature2/Android.mk b/tests/FeatureSplit/feature2/Android.mk
deleted file mode 100644
index 5e5e78b..0000000
--- a/tests/FeatureSplit/feature2/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit2
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x81
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.two
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp
new file mode 100644
index 0000000..5608a2b
--- /dev/null
+++ b/tests/FixVibrateSetting/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "FixVibrateSetting",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/FixVibrateSetting/Android.mk b/tests/FixVibrateSetting/Android.mk
deleted file mode 100644
index 86db09e..0000000
--- a/tests/FixVibrateSetting/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FixVibrateSetting
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/Android.bp b/tests/FrameworkPerf/Android.bp
new file mode 100644
index 0000000..a259ebd
--- /dev/null
+++ b/tests/FrameworkPerf/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+    name: "FrameworkPerf",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    aaptflags: [
+        "-c",
+        "120dpi,240dpi,160dpi,161dpi,320dpi,nodpi",
+    ],
+}
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
deleted file mode 100644
index 0664d4d..0000000
--- a/tests/FrameworkPerf/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FrameworkPerf
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/GridLayoutTest/Android.bp b/tests/GridLayoutTest/Android.bp
new file mode 100644
index 0000000..b4b5ba5
--- /dev/null
+++ b/tests/GridLayoutTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2010 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.
+//
+
+android_test {
+    name: "GridLayoutTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/GridLayoutTest/Android.mk b/tests/GridLayoutTest/Android.mk
deleted file mode 100644
index e7e3ccd..0000000
--- a/tests/GridLayoutTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GridLayoutTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HierarchyViewerTest/Android.bp b/tests/HierarchyViewerTest/Android.bp
new file mode 100644
index 0000000..814c883
--- /dev/null
+++ b/tests/HierarchyViewerTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "HierarchyViewerTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    static_libs: ["junit"],
+}
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
deleted file mode 100644
index cf1a512..0000000
--- a/tests/HierarchyViewerTest/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := HierarchyViewerTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HugeBackup/Android.bp b/tests/HugeBackup/Android.bp
new file mode 100644
index 0000000..b44c457
--- /dev/null
+++ b/tests/HugeBackup/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "HugeBackup",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+}
diff --git a/tests/HugeBackup/Android.mk b/tests/HugeBackup/Android.mk
deleted file mode 100644
index 4789bc8..0000000
--- a/tests/HugeBackup/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := HugeBackup
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
index d92cfce..300182d 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java
@@ -27,7 +27,6 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
-import com.android.internal.graphics.ColorUtils;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -96,7 +95,6 @@
         Tonal.ConfigParser config = new Tonal.ConfigParser(InstrumentationRegistry.getContext());
         // 1 to avoid regression where only first item would be parsed.
         assertTrue("Tonal palettes are empty", config.getTonalPalettes().size() > 1);
-        assertTrue("Blacklisted colors are empty", config.getBlacklistedColors().size() > 1);
     }
 
     @Test
@@ -113,41 +111,4 @@
             assertTrue("L should be <= to 1.", palette.l[1] <= 1);
         }
     }
-
-    @Test
-    public void tonal_blacklistTest() {
-        // Make sure that palette generation will fail.
-        final Tonal tonal = new Tonal(InstrumentationRegistry.getContext());
-
-        // Creating a WallpaperColors object that contains *only* blacklisted colors.
-        final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter();
-        final int blacklistedColor = ColorUtils.HSLToColor(hsl);
-        WallpaperColors colorsFromBitmap = new WallpaperColors(Color.valueOf(blacklistedColor),
-                null, null, WallpaperColors.HINT_FROM_BITMAP);
-
-        // Make sure that palette generation will fail
-        final GradientColors normal = new GradientColors();
-        tonal.extractInto(colorsFromBitmap, normal, new GradientColors(),
-                new GradientColors());
-        assertTrue("Cannot generate a tonal palette from blacklisted colors.",
-                normal.getMainColor() == Tonal.MAIN_COLOR_DARK);
-    }
-
-    @Test
-    public void tonal_ignoreBlacklistTest() {
-        final Tonal tonal = new Tonal(InstrumentationRegistry.getContext());
-
-        // Creating a WallpaperColors object that contains *only* blacklisted colors.
-        final float[] hsl = tonal.getBlacklistedColors().get(0).getCenter();
-        final int blacklistedColor = ColorUtils.HSLToColor(hsl);
-        WallpaperColors colors = new WallpaperColors(Color.valueOf(blacklistedColor),
-                null, null);
-
-        // Blacklist should be ignored when HINT_FROM_BITMAP isn't present.
-        final GradientColors normal = new GradientColors();
-        tonal.extractInto(colors, normal, new GradientColors(),
-                new GradientColors());
-        assertTrue("Blacklist should never be used on WallpaperColors generated using "
-                + "default constructor.", normal.getMainColor() == blacklistedColor);
-    }
 }
diff --git a/tests/JobSchedulerTestApp/Android.bp b/tests/JobSchedulerTestApp/Android.bp
new file mode 100644
index 0000000..bac0220
--- /dev/null
+++ b/tests/JobSchedulerTestApp/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "JobSchedulerTestApp",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "current",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/JobSchedulerTestApp/Android.mk b/tests/JobSchedulerTestApp/Android.mk
deleted file mode 100644
index 48ee1f6..0000000
--- a/tests/JobSchedulerTestApp/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := JobSchedulerTestApp
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/LargeAssetTest/Android.bp b/tests/LargeAssetTest/Android.bp
new file mode 100644
index 0000000..499e6a0
--- /dev/null
+++ b/tests/LargeAssetTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "LargeAssetTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/LargeAssetTest/Android.mk b/tests/LargeAssetTest/Android.mk
deleted file mode 100644
index f6d98bf..0000000
--- a/tests/LargeAssetTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LargeAssetTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LegacyAssistant/Android.bp b/tests/LegacyAssistant/Android.bp
new file mode 100644
index 0000000..fef924d
--- /dev/null
+++ b/tests/LegacyAssistant/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "LegacyAssistant",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/LegacyAssistant/Android.mk b/tests/LegacyAssistant/Android.mk
deleted file mode 100644
index a583369..0000000
--- a/tests/LegacyAssistant/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LegacyAssistant
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LocationTracker/Android.bp b/tests/LocationTracker/Android.bp
new file mode 100644
index 0000000..f0075a9
--- /dev/null
+++ b/tests/LocationTracker/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "LocationTracker",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/LocationTracker/Android.mk b/tests/LocationTracker/Android.mk
deleted file mode 100644
index 0d51b3b..0000000
--- a/tests/LocationTracker/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LocationTracker
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LotsOfApps/Android.bp b/tests/LotsOfApps/Android.bp
new file mode 100644
index 0000000..68b9f88
--- /dev/null
+++ b/tests/LotsOfApps/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "LotsOfApps",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/LotsOfApps/Android.mk b/tests/LotsOfApps/Android.mk
deleted file mode 100644
index bee3bcc..0000000
--- a/tests/LotsOfApps/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LotsOfApps
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LowStorageTest/Android.bp b/tests/LowStorageTest/Android.bp
new file mode 100644
index 0000000..e72e4a5
--- /dev/null
+++ b/tests/LowStorageTest/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2009 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.
+
+android_test {
+    name: "lowstoragetest",
+    certificate: "platform",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/LowStorageTest/Android.mk b/tests/LowStorageTest/Android.mk
deleted file mode 100644
index bdde6bd..0000000
--- a/tests/LowStorageTest/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2009 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := lowstoragetest
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/MemoryUsage/Android.bp b/tests/MemoryUsage/Android.bp
new file mode 100644
index 0000000..aeb5338
--- /dev/null
+++ b/tests/MemoryUsage/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "MemoryUsage",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
deleted file mode 100644
index 5040d5a..0000000
--- a/tests/MemoryUsage/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MemoryUsage
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/NetworkSecurityConfigTest/Android.bp b/tests/NetworkSecurityConfigTest/Android.bp
new file mode 100644
index 0000000..cf8ca57
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "NetworkSecurityConfigTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
deleted file mode 100644
index a6c21db..0000000
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner \
-    android.test.base \
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NetworkSecurityConfigTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
new file mode 100644
index 0000000..d86f9cc
--- /dev/null
+++ b/tests/OdmApps/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_test_host {
+    name: "OdmAppsTest",
+    srcs: ["src/**/*.java"],
+    libs: ["tradefed"],
+    test_suites: ["device-tests"],
+}
diff --git a/tests/OdmApps/Android.mk b/tests/OdmApps/Android.mk
deleted file mode 100644
index 64fa653..0000000
--- a/tests/OdmApps/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := OdmAppsTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := tradefed
-LOCAL_COMPATIBILITY_SUITE := device-tests
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/OdmApps/app/Android.bp b/tests/OdmApps/app/Android.bp
new file mode 100644
index 0000000..5eb8590
--- /dev/null
+++ b/tests/OdmApps/app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "TestOdmApp",
+    test_suites: ["device-tests"],
+    sdk_version: "current",
+}
diff --git a/tests/OdmApps/app/Android.mk b/tests/OdmApps/app/Android.mk
deleted file mode 100644
index 9eec0cc..0000000
--- a/tests/OdmApps/app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/priv-app/Android.bp b/tests/OdmApps/priv-app/Android.bp
new file mode 100644
index 0000000..9dd477cf
--- /dev/null
+++ b/tests/OdmApps/priv-app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "TestOdmPrivApp",
+    test_suites: ["device-tests"],
+    sdk_version: "current",
+}
diff --git a/tests/OdmApps/priv-app/Android.mk b/tests/OdmApps/priv-app/Android.mk
deleted file mode 100644
index d423133..0000000
--- a/tests/OdmApps/priv-app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmPrivApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp
new file mode 100644
index 0000000..11e12f35
--- /dev/null
+++ b/tests/OneMedia/Android.bp
@@ -0,0 +1,13 @@
+android_app {
+    name: "OneMedia",
+    srcs: [
+        "**/*.java",
+        "src/**/I*.aidl",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+    libs: ["org.apache.http.legacy"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
deleted file mode 100644
index 41f3f64..0000000
--- a/tests/OneMedia/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-        $(call all-Iaidl-files-under, src)
-
-LOCAL_PACKAGE_NAME := OneMedia
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RemoteDisplayProvider/Android.bp b/tests/RemoteDisplayProvider/Android.bp
new file mode 100644
index 0000000..6c7798f
--- /dev/null
+++ b/tests/RemoteDisplayProvider/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "RemoteDisplayProviderTest",
+    sdk_version: "system_current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    libs: ["com.android.media.remotedisplay"],
+    certificate: "platform",
+}
diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk
deleted file mode 100644
index 43bf024..0000000
--- a/tests/RemoteDisplayProvider/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := RemoteDisplayProviderTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := system_current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay
-LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderThreadTest/Android.bp b/tests/RenderThreadTest/Android.bp
new file mode 100644
index 0000000..1659776
--- /dev/null
+++ b/tests/RenderThreadTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "RenderThreadTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    static_libs: ["android-common"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk
deleted file mode 100644
index 4e5f35b..0000000
--- a/tests/RenderThreadTest/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := RenderThreadTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SerialChat/Android.bp b/tests/SerialChat/Android.bp
new file mode 100644
index 0000000..3c18035
--- /dev/null
+++ b/tests/SerialChat/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "SerialChat",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/SerialChat/Android.mk b/tests/SerialChat/Android.mk
deleted file mode 100644
index ed6ca999..0000000
--- a/tests/SerialChat/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SerialChat
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/client/Android.bp b/tests/SharedLibrary/client/Android.bp
new file mode 100644
index 0000000..dbf6dc9
--- /dev/null
+++ b/tests/SharedLibrary/client/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "SharedLibraryClient",
+    srcs: ["**/*.java"],
+    libs: ["SharedLibrary"],
+    sdk_version: "current",
+}
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
deleted file mode 100644
index 9e76c40..0000000
--- a/tests/SharedLibrary/client/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RES_LIBRARIES := SharedLibrary
-
-LOCAL_PACKAGE_NAME := SharedLibraryClient
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/lib/Android.bp b/tests/SharedLibrary/lib/Android.bp
new file mode 100644
index 0000000..f69d388
--- /dev/null
+++ b/tests/SharedLibrary/lib/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+    name: "SharedLibrary",
+    srcs: ["**/*.java"],
+    aaptflags: ["--shared-lib"],
+    sdk_version: "current",
+    export_package_resources: true,
+    privileged: true,
+    optimize: {
+        proguard_flags_files: ["proguard.proguard"],
+    },
+}
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
deleted file mode 100644
index 3c1ca87..0000000
--- a/tests/SharedLibrary/lib/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_AAPT_FLAGS := --shared-lib
-LOCAL_PACKAGE_NAME := SharedLibrary
-LOCAL_SDK_VERSION := current
-
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
-
-include $(BUILD_PACKAGE)
diff --git a/tests/ShowWhenLockedApp/Android.bp b/tests/ShowWhenLockedApp/Android.bp
new file mode 100644
index 0000000..dba564c
--- /dev/null
+++ b/tests/ShowWhenLockedApp/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "ShowWhenLocked",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/ShowWhenLockedApp/Android.mk b/tests/ShowWhenLockedApp/Android.mk
deleted file mode 100644
index 41e0ac4..0000000
--- a/tests/ShowWhenLockedApp/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ShowWhenLocked
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/SmokeTest/Android.bp b/tests/SmokeTest/Android.bp
new file mode 100644
index 0000000..bc45ee6
--- /dev/null
+++ b/tests/SmokeTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "SmokeTestApp",
+    // This builds "SmokeTestApp"
+    srcs: ["src/**/*.java"],
+    sdk_version: "8",
+}
diff --git a/tests/SmokeTest/Android.mk b/tests/SmokeTest/Android.mk
deleted file mode 100644
index 591a84e..0000000
--- a/tests/SmokeTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# This builds "SmokeTestApp"
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-# This builds "SmokeTest"
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SmokeTest/tests/Android.bp b/tests/SmokeTest/tests/Android.bp
new file mode 100644
index 0000000..ceb2d19
--- /dev/null
+++ b/tests/SmokeTest/tests/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "SmokeTest",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    // Notice that we don't have to include the src files of SmokeTestApp because, by
+    // running the tests using an instrumentation targeting SmokeTestApp, we
+    // automatically get all of its classes loaded into our environment.
+    instrumentation_for: "SmokeTestApp",
+    sdk_version: "8",
+}
diff --git a/tests/SmokeTest/tests/Android.mk b/tests/SmokeTest/tests/Android.mk
deleted file mode 100644
index 18e682e..0000000
--- a/tests/SmokeTest/tests/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Notice that we don't have to include the src files of SmokeTestApp because, by
-# running the tests using an instrumentation targeting SmokeTestApp, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := SmokeTest
-
-LOCAL_INSTRUMENTATION_FOR := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp
new file mode 100644
index 0000000..0feb0004
--- /dev/null
+++ b/tests/SmokeTestApps/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "SmokeTestTriggerApps",
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/SmokeTestApps/Android.mk b/tests/SmokeTestApps/Android.mk
deleted file mode 100644
index 1f564e0..0000000
--- a/tests/SmokeTestApps/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestTriggerApps
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SoundTriggerTestApp/Android.bp b/tests/SoundTriggerTestApp/Android.bp
new file mode 100644
index 0000000..d3a1300
--- /dev/null
+++ b/tests/SoundTriggerTestApp/Android.bp
@@ -0,0 +1,7 @@
+android_app {
+    name: "SoundTriggerTestApp",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    privileged: true,
+    certificate: "platform",
+}
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
deleted file mode 100644
index 73fb5e8..0000000
--- a/tests/SoundTriggerTestApp/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SoundTriggerTestApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Split/Android.bp b/tests/Split/Android.bp
new file mode 100644
index 0000000..d8c89ba
--- /dev/null
+++ b/tests/Split/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+android_test {
+    name: "Split",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    package_splits: [
+        "mdpi-v4",
+        "hdpi-v4",
+        "xhdpi-v4",
+        "xxhdpi-v4",
+    ],
+}
diff --git a/tests/Split/Android.mk b/tests/Split/Android.mk
deleted file mode 100644
index 4d15b2d..0000000
--- a/tests/Split/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := Split
-LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/StatusBar/Android.bp b/tests/StatusBar/Android.bp
new file mode 100644
index 0000000..0b650ed
--- /dev/null
+++ b/tests/StatusBar/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "StatusBarTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/StatusBar/Android.mk b/tests/StatusBar/Android.mk
deleted file mode 100644
index e845335..0000000
--- a/tests/StatusBar/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := StatusBarTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SystemUIDemoModeController/Android.bp b/tests/SystemUIDemoModeController/Android.bp
new file mode 100644
index 0000000..1e4c437
--- /dev/null
+++ b/tests/SystemUIDemoModeController/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "DemoModeController",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
deleted file mode 100644
index cc6fa8d..0000000
--- a/tests/SystemUIDemoModeController/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DemoModeController
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
new file mode 100644
index 0000000..1174bcb0
--- /dev/null
+++ b/tests/TouchLatency/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "TouchLatency",
+    manifest: "app/src/main/AndroidManifest.xml",
+    // omit gradle 'build' dir
+    srcs: ["app/src/main/java/**/*.java"],
+    resource_dirs: ["app/src/main/res"],
+    aaptflags: ["--auto-add-overlay"],
+    sdk_version: "current",
+    test_suites: ["device-tests"],
+}
diff --git a/tests/TouchLatency/Android.mk b/tests/TouchLatency/Android.mk
deleted file mode 100644
index 2334bd8..0000000
--- a/tests/TouchLatency/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
-
-# omit gradle 'build' dir
-LOCAL_SRC_FILES := $(call all-java-files-under,app/src/main/java)
-
-LOCAL_RESOURCE_DIR := \
-    $(LOCAL_PATH)/app/src/main/res
-
-LOCAL_AAPT_FLAGS := \
-    --auto-add-overlay
-
-LOCAL_PACKAGE_NAME := TouchLatency
-LOCAL_SDK_VERSION := current
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransformTest/Android.bp b/tests/TransformTest/Android.bp
new file mode 100644
index 0000000..fd7aaeb
--- /dev/null
+++ b/tests/TransformTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "TransformTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/TransformTest/Android.mk b/tests/TransformTest/Android.mk
deleted file mode 100644
index 5340cdd..0000000
--- a/tests/TransformTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TransformTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransitionTests/Android.bp b/tests/TransitionTests/Android.bp
new file mode 100644
index 0000000..57f19e3
--- /dev/null
+++ b/tests/TransitionTests/Android.bp
@@ -0,0 +1,10 @@
+android_app {
+    name: "TransitionTests",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    static_libs: ["android-common"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/TransitionTests/Android.mk b/tests/TransitionTests/Android.mk
deleted file mode 100644
index a696156..0000000
--- a/tests/TransitionTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := TransitionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/TtsTests/Android.bp b/tests/TtsTests/Android.bp
new file mode 100644
index 0000000..b137523
--- /dev/null
+++ b/tests/TtsTests/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "TtsTests",
+    srcs: ["**/*.java"],
+    static_libs: ["mockito-target"],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    platform_apis: true,
+}
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
deleted file mode 100644
index 116cc0a..0000000
--- a/tests/TtsTests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-
-LOCAL_PACKAGE_NAME := TtsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsesFeature2Test/Android.bp b/tests/UsesFeature2Test/Android.bp
new file mode 100644
index 0000000..a1b77d0
--- /dev/null
+++ b/tests/UsesFeature2Test/Android.bp
@@ -0,0 +1,21 @@
+//
+// 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.
+//
+
+android_test {
+    name: "UsesFeature2Test",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/UsesFeature2Test/Android.mk b/tests/UsesFeature2Test/Android.mk
deleted file mode 100644
index 4cba4ff..0000000
--- a/tests/UsesFeature2Test/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := UsesFeature2Test
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp
new file mode 100644
index 0000000..13f318e
--- /dev/null
+++ b/tests/VectorDrawableTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// 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.
+//
+
+android_test {
+    name: "VectorDrawableTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/VectorDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
deleted file mode 100644
index 155b2bc..0000000
--- a/tests/VectorDrawableTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VectorDrawableTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceEnrollment/Android.bp b/tests/VoiceEnrollment/Android.bp
new file mode 100644
index 0000000..e43b38c
--- /dev/null
+++ b/tests/VoiceEnrollment/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "VoiceEnrollment",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    privileged: true,
+}
diff --git a/tests/VoiceEnrollment/Android.mk b/tests/VoiceEnrollment/Android.mk
deleted file mode 100644
index 725e2bd..0000000
--- a/tests/VoiceEnrollment/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceEnrollment
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceInteraction/Android.bp b/tests/VoiceInteraction/Android.bp
new file mode 100644
index 0000000..7059473
--- /dev/null
+++ b/tests/VoiceInteraction/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "VoiceInteraction",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/VoiceInteraction/Android.mk b/tests/VoiceInteraction/Android.mk
deleted file mode 100644
index aa48b42..0000000
--- a/tests/VoiceInteraction/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceInteraction
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/WallpaperTest/Android.bp b/tests/WallpaperTest/Android.bp
new file mode 100644
index 0000000..f68b6ec
--- /dev/null
+++ b/tests/WallpaperTest/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "WallpaperTest",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    platform_apis: true,
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
deleted file mode 100644
index 4815500..0000000
--- a/tests/WallpaperTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := WallpaperTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/WindowManagerStressTest/Android.bp b/tests/WindowManagerStressTest/Android.bp
new file mode 100644
index 0000000..98749a7
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_test {
+    name: "WindowManagerStressTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
deleted file mode 100644
index 6f4403f..0000000
--- a/tests/WindowManagerStressTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := WindowManagerStressTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.bp b/tests/appwidgets/AppWidgetHostTest/Android.bp
new file mode 100644
index 0000000..24b7613
--- /dev/null
+++ b/tests/appwidgets/AppWidgetHostTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "AppWidgetHostTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.mk b/tests/appwidgets/AppWidgetHostTest/Android.mk
deleted file mode 100644
index c9e6c6b..0000000
--- a/tests/appwidgets/AppWidgetHostTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetHostTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.bp b/tests/appwidgets/AppWidgetProviderTest/Android.bp
new file mode 100644
index 0000000..a1a5991
--- /dev/null
+++ b/tests/appwidgets/AppWidgetProviderTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "AppWidgetProvider",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.mk b/tests/appwidgets/AppWidgetProviderTest/Android.mk
deleted file mode 100644
index b26c60b..0000000
--- a/tests/appwidgets/AppWidgetProviderTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetProvider
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
new file mode 100644
index 0000000..2539c0f
--- /dev/null
+++ b/tests/net/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// Build FrameworksNetTests package
+//########################################################################
+
+android_test {
+    name: "FrameworksNetTests",
+    // Include all test java files.
+    srcs: ["java/**/*.java"],
+    static_libs: [
+        "frameworks-base-testutils",
+        "framework-protos",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+        "platform-test-annotations",
+        "services.core",
+        "services.ipmemorystore",
+        "services.net",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    certificate: "platform",
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
deleted file mode 100644
index 2ef141f..0000000
--- a/tests/net/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#########################################################################
-# Build FrameworksNetTests package
-#########################################################################
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    frameworks-base-testutils \
-    framework-protos \
-    androidx.test.rules \
-    mockito-target-minus-junit4 \
-    platform-test-annotations \
-    services.core \
-    services.ipmemorystore \
-    services.net
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner \
-    android.test.base \
-    android.test.mock
-
-LOCAL_PACKAGE_NAME := FrameworksNetTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
index 7311eee..d3836d4 100644
--- a/tests/net/OWNERS
+++ b/tests/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/tests/net/java/android/net/DnsPacketTest.java b/tests/net/java/android/net/DnsPacketTest.java
index 91ff6b3..9ede2b8 100644
--- a/tests/net/java/android/net/DnsPacketTest.java
+++ b/tests/net/java/android/net/DnsPacketTest.java
@@ -36,19 +36,19 @@
             int qCount, int aCount, int nsCount, int arCount) {
         assertEquals(header.id, id);
         assertEquals(header.flags, flag);
-        assertEquals(header.getSectionCount(DnsPacket.QDSECTION), qCount);
-        assertEquals(header.getSectionCount(DnsPacket.ANSECTION), aCount);
-        assertEquals(header.getSectionCount(DnsPacket.NSSECTION), nsCount);
-        assertEquals(header.getSectionCount(DnsPacket.ARSECTION), arCount);
+        assertEquals(header.getRecordCount(DnsPacket.QDSECTION), qCount);
+        assertEquals(header.getRecordCount(DnsPacket.ANSECTION), aCount);
+        assertEquals(header.getRecordCount(DnsPacket.NSSECTION), nsCount);
+        assertEquals(header.getRecordCount(DnsPacket.ARSECTION), arCount);
     }
 
-    private void assertSectionParses(DnsPacket.DnsSection section, String dname,
+    private void assertRecordParses(DnsPacket.DnsRecord record, String dname,
             int dtype, int dclass, int ttl, byte[] rr) {
-        assertEquals(section.dName, dname);
-        assertEquals(section.nsType, dtype);
-        assertEquals(section.nsClass, dclass);
-        assertEquals(section.ttl, ttl);
-        assertTrue(Arrays.equals(section.getRR(), rr));
+        assertEquals(record.dName, dname);
+        assertEquals(record.nsType, dtype);
+        assertEquals(record.nsClass, dclass);
+        assertEquals(record.ttl, ttl);
+        assertTrue(Arrays.equals(record.getRR(), rr));
     }
 
     class TestDnsPacket extends DnsPacket {
@@ -59,8 +59,8 @@
         public DnsHeader getHeader() {
             return mHeader;
         }
-        public List<DnsSection> getSectionList(int secType) {
-            return mSections[secType];
+        public List<DnsRecord> getRecordList(int secType) {
+            return mRecords[secType];
         }
     }
 
@@ -101,16 +101,16 @@
         // Header part
         assertHeaderParses(packet.getHeader(), 0x5566, 0x8180, 1, 1, 0, 0);
 
-        // Section part
-        List<DnsPacket.DnsSection> qdSectionList =
-                packet.getSectionList(DnsPacket.QDSECTION);
-        assertEquals(qdSectionList.size(), 1);
-        assertSectionParses(qdSectionList.get(0), "www.google.com", 1, 1, 0, null);
+        // Record part
+        List<DnsPacket.DnsRecord> qdRecordList =
+                packet.getRecordList(DnsPacket.QDSECTION);
+        assertEquals(qdRecordList.size(), 1);
+        assertRecordParses(qdRecordList.get(0), "www.google.com", 1, 1, 0, null);
 
-        List<DnsPacket.DnsSection> anSectionList =
-                packet.getSectionList(DnsPacket.ANSECTION);
-        assertEquals(anSectionList.size(), 1);
-        assertSectionParses(anSectionList.get(0), "www.google.com", 1, 1, 0x12b,
+        List<DnsPacket.DnsRecord> anRecordList =
+                packet.getRecordList(DnsPacket.ANSECTION);
+        assertEquals(anRecordList.size(), 1);
+        assertRecordParses(anRecordList.get(0), "www.google.com", 1, 1, 0x12b,
                 new byte[]{ (byte) 0xac, (byte) 0xd9, (byte) 0xa1, (byte) 0x84 });
     }
 
@@ -143,16 +143,16 @@
         // Header part
         assertHeaderParses(packet.getHeader(), 0x7722, 0x8180, 1, 1, 0, 0);
 
-        // Section part
-        List<DnsPacket.DnsSection> qdSectionList =
-                packet.getSectionList(DnsPacket.QDSECTION);
-        assertEquals(qdSectionList.size(), 1);
-        assertSectionParses(qdSectionList.get(0), "www.google.com", 28, 1, 0, null);
+        // Record part
+        List<DnsPacket.DnsRecord> qdRecordList =
+                packet.getRecordList(DnsPacket.QDSECTION);
+        assertEquals(qdRecordList.size(), 1);
+        assertRecordParses(qdRecordList.get(0), "www.google.com", 28, 1, 0, null);
 
-        List<DnsPacket.DnsSection> anSectionList =
-                packet.getSectionList(DnsPacket.ANSECTION);
-        assertEquals(anSectionList.size(), 1);
-        assertSectionParses(anSectionList.get(0), "www.google.com", 28, 1, 0x37,
+        List<DnsPacket.DnsRecord> anRecordList =
+                packet.getRecordList(DnsPacket.ANSECTION);
+        assertEquals(anRecordList.size(), 1);
+        assertRecordParses(anRecordList.get(0), "www.google.com", 28, 1, 0x37,
                 new byte[]{ 0x24, 0x04, 0x68, 0x00, 0x40, 0x05, 0x08, 0x0d,
                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04 });
     }
diff --git a/tests/notification/Android.bp b/tests/notification/Android.bp
new file mode 100644
index 0000000..f05edaf
--- /dev/null
+++ b/tests/notification/Android.bp
@@ -0,0 +1,7 @@
+android_test {
+    name: "NotificationTests",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.runner.stubs"],
+    sdk_version: "21",
+}
diff --git a/tests/notification/Android.mk b/tests/notification/Android.mk
deleted file mode 100644
index 255e6e7..0000000
--- a/tests/notification/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_PACKAGE_NAME := NotificationTests
-
-LOCAL_SDK_VERSION := 21
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp
new file mode 100644
index 0000000..bd07009
--- /dev/null
+++ b/tests/permission/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "FrameworkPermissionTests",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    libs: [
+        "android.test.runner",
+        "telephony-common",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    platform_apis: true,
+}
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
deleted file mode 100644
index dd2f3ec..0000000
--- a/tests/permission/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_PACKAGE_NAME := FrameworkPermissionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp
index 0bad7a4..eb6811c 100644
--- a/tests/testables/Android.bp
+++ b/tests/testables/Android.bp
@@ -15,18 +15,12 @@
 //
 
 java_library {
-
     name: "testables",
-    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_MODULE_TAG
-    // LOCAL_MODULE_TAG := tests
-
     srcs: ["src/**/*.java"],
-
     libs: [
         "android.test.runner",
         "android.test.mock",
         "androidx.test.rules",
         "mockito-target-inline-minus-junit4",
     ],
-
 }
diff --git a/tests/testables/tests/Android.bp b/tests/testables/tests/Android.bp
new file mode 100644
index 0000000..e1a58be
--- /dev/null
+++ b/tests/testables/tests/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+android_test {
+    name: "TestablesTests",
+    platform_apis: true,
+    srcs: [
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+    resource_dirs: ["res"],
+    static_libs: [
+        "androidx.test.rules",
+        "hamcrest-library",
+        "mockito-target-inline-minus-junit4",
+        "testables",
+    ],
+    compile_multilib: "both",
+    jni_libs: [
+        "libdexmakerjvmtiagent",
+        "libmultiplejvmtiagentsinterferenceagent",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+    certificate: "platform",
+    test_suites: ["device-tests"],
+}
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
deleted file mode 100644
index 16fbb18..0000000
--- a/tests/testables/tests/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := TestablesTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules hamcrest-library \
-    mockito-target-inline-minus-junit4 \
-	testables
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libdexmakerjvmtiagent \
-    libmultiplejvmtiagentsinterferenceagent
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/touchlag/Android.bp b/tests/touchlag/Android.bp
index 2610cb3..092eea9 100644
--- a/tests/touchlag/Android.bp
+++ b/tests/touchlag/Android.bp
@@ -1,14 +1,11 @@
 cc_test {
     name: "test-touchlag",
     gtest: false,
-
     srcs: ["touchlag.cpp"],
-
     shared_libs: [
         "libcutils",
         "libutils",
     ],
-
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/tests/utils/Android.mk b/tests/utils/Android.mk
deleted file mode 100644
index c141484..0000000
--- a/tests/utils/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/tests/utils/DummyIME/Android.bp b/tests/utils/DummyIME/Android.bp
new file mode 100644
index 0000000..4a44b3b
--- /dev/null
+++ b/tests/utils/DummyIME/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2012 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.
+//
+
+android_test {
+    name: "DummyIME",
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/utils/DummyIME/Android.mk b/tests/utils/DummyIME/Android.mk
deleted file mode 100644
index 0f6c988..0000000
--- a/tests/utils/DummyIME/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DummyIME
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 2a8f695..6781eba 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -29,6 +29,9 @@
 FLAG_GREYLIST_MAX_O = "greylist-max-o"
 FLAG_GREYLIST_MAX_P = "greylist-max-p"
 FLAG_CORE_PLATFORM_API = "core-platform-api"
+FLAG_PUBLIC_API = "public-api"
+FLAG_SYSTEM_API = "system-api"
+FLAG_TEST_API = "test-api"
 
 # List of all known flags.
 FLAGS_API_LIST = [
@@ -38,7 +41,12 @@
     FLAG_GREYLIST_MAX_O,
     FLAG_GREYLIST_MAX_P,
 ]
-ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API ]
+ALL_FLAGS = FLAGS_API_LIST + [
+    FLAG_CORE_PLATFORM_API,
+    FLAG_PUBLIC_API,
+    FLAG_SYSTEM_API,
+    FLAG_TEST_API,
+    ]
 
 FLAGS_API_LIST_SET = set(FLAGS_API_LIST)
 ALL_FLAGS_SET = set(ALL_FLAGS)
@@ -203,14 +211,19 @@
 
         # Iterate over all CSV lines, find entry in dict and append flags to it.
         for csv in csv_values:
-            self._dict[csv[0]].update(csv[1:])
+            flags = csv[1:]
+            if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
+                flags.append(FLAG_WHITELIST)
+            elif FLAG_TEST_API in flags:
+                flags.append(FLAG_GREYLIST)
+            self._dict[csv[0]].update(flags)
 
     def assign_flag(self, flag, apis, source="<unknown>"):
         """Assigns a flag to given subset of entries.
 
         Args:
             flag (string): One of ALL_FLAGS.
-            apis (set): Subset of APIs to recieve the flag.
+            apis (set): Subset of APIs to receive the flag.
             source (string): Origin of `entries_subset`. Will be printed in error messages.
 
         Throws: