Merge "IMS: Support Robocall Feature For MT VOLTE Calls"
diff --git a/Android.bp b/Android.bp
index 07b3018..759014f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1179,6 +1179,48 @@
     create_stubs: false,
 }
 
+metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+    "--hide-package com.android.okhttp " +
+    "--hide-package com.android.org.conscrypt --hide-package com.android.server " +
+    "--hide RequiresPermission " +
+    "--hide MissingPermission --hide BroadcastBehavior " +
+    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
+
+doc_defaults {
+    name: "metalava-api-stubs-default",
+    srcs: [
+        ":opt-telephony-srcs",
+        ":opt-net-voip-srcs",
+        ":openjdk_javadoc_files",
+        ":non_openjdk_javadoc_files",
+        ":android_icu4j_src_files_for_docs",
+    ],
+    srcs_lib: "framework",
+    srcs_lib_whitelist_dirs: frameworks_base_subdirs,
+    srcs_lib_whitelist_pkgs: packages_to_document,
+    libs: [
+        "core-oj",
+        "core-libart",
+        "conscrypt",
+        "bouncycastle",
+        "okhttp",
+        "ext",
+        "framework",
+        "voip-common",
+        "android.test.mock.impl",
+    ],
+    local_sourcepaths: frameworks_base_subdirs,
+    installable: false,
+    metalava_enabled: true,
+    metalava_annotations_enabled: true,
+    metalava_previous_api: ":last-released-public-api",
+    metalava_merge_annotations_dirs: [
+        "metalava-manual",
+        "ojluni-annotated-stubs",
+    ],
+}
+
 droiddoc {
     name: "doc-comment-check-docs",
     defaults: ["framework-docs-default"],
@@ -1406,26 +1448,21 @@
 }
 
 droiddoc {
-    name: "hiddenapi-lists",
-    defaults: ["api-stubs-default"],
+    name: "hiddenapi-lists-docs",
+    defaults: ["metalava-api-stubs-default"],
     arg_files: [
         "core/res/AndroidManifest.xml",
-        ":api-version-xml",
-        "core/java/overview.html",
-        ":current-support-api",
-        "api/current.txt",
     ],
     dex_api_filename: "public-dex.txt",
     private_dex_api_filename: "private-dex.txt",
     removed_dex_api_filename: "removed-dex.txt",
-    args: framework_docs_args +
-          " -referenceonly" +
-          " -nodocs" +
-          " -showUnannotated" +
-          " -showAnnotation android.annotation.SystemApi" +
-          " -showAnnotation android.annotation.TestApi",
+    args: metalava_framework_docs_args +
+        " --show-unannotated " +
+        " --show-annotation android.annotation.SystemApi " +
+        " --show-annotation android.annotation.TestApi "
 }
 
+
 droiddoc {
     name: "hiddenapi-mappings",
     defaults: ["api-stubs-default"],
@@ -1469,48 +1506,6 @@
     ],
 }
 
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
-    "--hide-package com.android.okhttp " +
-    "--hide-package com.android.org.conscrypt --hide-package com.android.server " +
-    "--hide RequiresPermission " +
-    "--hide MissingPermission --hide BroadcastBehavior " +
-    "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
-    "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
-
-doc_defaults {
-    name: "metalava-api-stubs-default",
-    srcs: [
-        ":opt-telephony-srcs",
-        ":opt-net-voip-srcs",
-        ":openjdk_javadoc_files",
-        ":non_openjdk_javadoc_files",
-        ":android_icu4j_src_files_for_docs",
-    ],
-    srcs_lib: "framework",
-    srcs_lib_whitelist_dirs: frameworks_base_subdirs,
-    srcs_lib_whitelist_pkgs: packages_to_document,
-    libs: [
-        "core-oj",
-        "core-libart",
-        "conscrypt",
-        "bouncycastle",
-        "okhttp",
-        "ext",
-        "framework",
-        "voip-common",
-        "android.test.mock.impl",
-    ],
-    local_sourcepaths: frameworks_base_subdirs,
-    installable: false,
-    metalava_enabled: true,
-    metalava_annotations_enabled: true,
-    metalava_previous_api: ":last-released-public-api",
-    metalava_merge_annotations_dirs: [
-        "metalava-manual",
-        "ojluni-annotated-stubs",
-    ],
-}
-
 droiddoc {
     name: "api-stubs-docs",
     defaults: ["metalava-api-stubs-default"],
diff --git a/api/current.txt b/api/current.txt
index 3a523f6..4d692ee 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8713,6 +8713,8 @@
     method public byte[] getServiceData();
     method public byte[] getServiceDataMask();
     method public android.os.ParcelUuid getServiceDataUuid();
+    method public android.os.ParcelUuid getServiceSolicitationUuid();
+    method public android.os.ParcelUuid getServiceSolicitationUuidMask();
     method public android.os.ParcelUuid getServiceUuid();
     method public android.os.ParcelUuid getServiceUuidMask();
     method public boolean matches(android.bluetooth.le.ScanResult);
@@ -8729,6 +8731,8 @@
     method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
     method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
     method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
+    method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid);
+    method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid, android.os.ParcelUuid);
     method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
     method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
   }
@@ -8741,6 +8745,7 @@
     method public byte[] getManufacturerSpecificData(int);
     method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData();
     method public byte[] getServiceData(android.os.ParcelUuid);
+    method public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
     method public java.util.List<android.os.ParcelUuid> getServiceUuids();
     method public int getTxPowerLevel();
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 4168353..3d8c494 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4542,11 +4542,9 @@
   public abstract class AutofillFieldClassificationService extends android.app.Service {
     method public android.os.IBinder onBind(android.content.Intent);
     method public float[][] onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>);
-    field public static final java.lang.String RESOURCE_AVAILABLE_ALGORITHMS = "autofill_field_classification_available_algorithms";
-    field public static final java.lang.String RESOURCE_DEFAULT_ALGORITHM = "autofill_field_classification_default_algorithm";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
-    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
-    field public static final deprecated java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
+    field public static final java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
+    field public static final java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 7947ed9..3a9d6a4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -335,6 +335,10 @@
 
 package android.database.sqlite {
 
+  public class SQLiteCompatibilityWalFlags {
+    method public static void reset();
+  }
+
   public final class SQLiteDebug {
     method public static void dump(android.util.Printer, java.lang.String[]);
     method public static android.database.sqlite.SQLiteDebug.PagerStats getDatabaseInfo();
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f27f7fb..6065bbf 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -151,16 +151,12 @@
         SystemUptime system_uptime = 10015;
         CpuActiveTime cpu_active_time = 10016;
         CpuClusterTime cpu_cluster_time = 10017;
-        DiskSpace disk_space = 10018 [deprecated=true];
+        DiskSpace disk_space = 10018;
         RemainingBatteryCapacity remaining_battery_capacity = 10019;
         FullBatteryCapacity full_battery_capacity = 10020;
         Temperature temperature = 10021;
         BinderCalls binder_calls = 10022;
         BinderCallsExceptions binder_calls_exceptions = 10023;
-        DiskStats disk_stats = 10024;
-        DirectoryUsage directory_usage = 10025;
-        AppSize app_size = 10026;
-        CategorySize category_size = 10027;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
@@ -2186,83 +2182,3 @@
     // Total number of exceptions.
     optional int64 exception_count = 2;
 }
-
-
-/**
- * Pulls disk information, such as write speed and latency.
- */
-message DiskStats {
-    // Time taken to open, write 512B to, and close a file.
-    // -1 if error performing the check.
-    optional int64 data_write_latency_millis = 1;
-
-    optional bool file_based_encryption = 2;
-
-    // Recent disk write speed in kB/s.
-    // -1 if error querying storageed.
-    // 0 if data is unavailable.
-    optional int32 recent_disk_write_speed = 3;
-}
-
-
-/**
- * Free and total bytes of the Data, Cache, and System partition.
- */
-message DirectoryUsage {
-    enum Directory {
-        UNKNOWN = 0;
-        DATA = 1;
-        CACHE = 2;
-        SYSTEM = 3;
-    }
-    optional Directory directory = 1;
-    optional int64 free_bytes = 2;
-    optional int64 total_bytes = 3;
-}
-
-
-/**
- * Size of an application: apk size, data size, and cache size.
- * Reads from a cached file produced daily by DiskStatsLoggingService.java.
- * Information is only reported for apps with the primary user (user 0).
- * Sizes are aggregated by package name.
- */
-message AppSize {
-    // Including uids will involve modifying diskstats logic.
-    optional string package_name = 1;
-    // App size in bytes. -1 if unavailable.
-    optional int64 app_size_bytes = 2;
-    // App data size in bytes. -1 if unavailable.
-    optional int64 app_data_size_bytes = 3;
-    // App cache size in bytes. -1 if unavailable.
-    optional int64 app_cache_size_bytes = 4;
-    // Time that the cache file was produced.
-    // Uses System.currentTimeMillis(), which is wall clock time.
-    optional int64 cache_time_millis = 5;
-}
-
-
-/**
- * Size of a particular category. Eg: photos, videos.
- * Reads from a cached file produced daily by DiskStatsLoggingService.java.
- */
-message CategorySize {
-    enum Category {
-        UNKNOWN = 0;
-        APP_SIZE = 1;
-        APP_DATA_SIZE = 2;
-        APP_CACHE_SIZE = 3;
-        PHOTOS = 4;
-        VIDEOS = 5;
-        AUDIO = 6;
-        DOWNLOADS = 7;
-        SYSTEM = 8;
-        OTHER = 9;
-    }
-    optional Category category = 1;
-    // Category size in bytes.
-    optional int64 size_bytes = 2;
-    // Time that the cache file was produced.
-    // Uses System.currentTimeMillis(), which is wall clock time.
-    optional int64 cache_time_millis = 3;
-}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 95510f5..e6e8455 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -149,6 +149,9 @@
         // system_uptime
         {android::util::SYSTEM_UPTIME,
          {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
+        // disk_space
+        {android::util::DISK_SPACE,
+         {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_SPACE)}},
         // remaining_battery_capacity
         {android::util::REMAINING_BATTERY_CAPACITY,
          {{},
@@ -180,31 +183,7 @@
          {{},
           {},
           1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
-        // Disk Stats
-        {android::util::DISK_STATS,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::DISK_STATS)}},
-        // Directory usage
-        {android::util::DIRECTORY_USAGE,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
-        // Size of app's code, data, and cache
-        {android::util::APP_SIZE,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::APP_SIZE)}},
-        // Size of specific categories of files. Eg. Music.
-        {android::util::CATEGORY_SIZE,
-         {{},
-          {},
-          1 * NS_PER_SEC,
-          new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
+          new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}
         };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 65a0a4b..6f06edc 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2172,47 +2172,7 @@
 Lcom/android/internal/statusbar/IStatusBarService;->setIconVisibility(Ljava/lang/String;Z)V
 Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
 Lcom/android/internal/telecom/ITelecomService;->getCallState()I
-Lcom/android/internal/telephony/CallerInfo;-><init>()V
-Lcom/android/internal/telephony/CallerInfo;->contactIdOrZero:J
-Lcom/android/internal/telephony/CallerInfo;->getCallerInfo(Landroid/content/Context;Landroid/net/Uri;)Lcom/android/internal/telephony/CallerInfo;
-Lcom/android/internal/telephony/CallerInfo;->getCallerInfo(Landroid/content/Context;Ljava/lang/String;)Lcom/android/internal/telephony/CallerInfo;
-Lcom/android/internal/telephony/CallerInfo;->getCallerInfo(Landroid/content/Context;Ljava/lang/String;I)Lcom/android/internal/telephony/CallerInfo;
-Lcom/android/internal/telephony/CallerInfo;->name:Ljava/lang/String;
-Lcom/android/internal/telephony/CallerInfo;->numberLabel:Ljava/lang/String;
-Lcom/android/internal/telephony/CallerInfo;->numberType:I
-Lcom/android/internal/telephony/CallerInfo;->phoneNumber:Ljava/lang/String;
-Lcom/android/internal/telephony/EncodeException;-><init>(C)V
-Lcom/android/internal/telephony/EncodeException;-><init>(Ljava/lang/String;)V
-Lcom/android/internal/telephony/GsmAlphabet$LanguagePairCount;-><init>(I)V
-Lcom/android/internal/telephony/GsmAlphabet$LanguagePairCount;->languageCode:I
-Lcom/android/internal/telephony/GsmAlphabet$LanguagePairCount;->septetCounts:[I
-Lcom/android/internal/telephony/GsmAlphabet$LanguagePairCount;->unencodableCounts:[I
 Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->codeUnitCount:I
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->codeUnitSize:I
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->codeUnitsRemaining:I
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->languageShiftTable:I
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->languageTable:I
-Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;->msgCount:I
-Lcom/android/internal/telephony/GsmAlphabet;->charToGsm(C)I
-Lcom/android/internal/telephony/GsmAlphabet;->charToGsm(CZ)I
-Lcom/android/internal/telephony/GsmAlphabet;->countGsmSeptets(CZ)I
-Lcom/android/internal/telephony/GsmAlphabet;->findGsmSeptetLimitIndex(Ljava/lang/String;IIII)I
-Lcom/android/internal/telephony/GsmAlphabet;->gsm7BitPackedToString([BIIIII)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->gsm8BitUnpackedToString([BII)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->gsm8BitUnpackedToString([BIILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->gsmToChar(I)C
-Lcom/android/internal/telephony/GsmAlphabet;->packSmsChar([BII)V
-Lcom/android/internal/telephony/GsmAlphabet;->sCharsToGsmTables:[Landroid/util/SparseIntArray;
-Lcom/android/internal/telephony/GsmAlphabet;->sCharsToShiftTables:[Landroid/util/SparseIntArray;
-Lcom/android/internal/telephony/GsmAlphabet;->sEnabledLockingShiftTables:[I
-Lcom/android/internal/telephony/GsmAlphabet;->sEnabledSingleShiftTables:[I
-Lcom/android/internal/telephony/GsmAlphabet;->sHighestEnabledSingleShiftCode:I
-Lcom/android/internal/telephony/GsmAlphabet;->sLanguageShiftTables:[Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->sLanguageTables:[Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->stringToGsm7BitPacked(Ljava/lang/String;IZII)[B
-Lcom/android/internal/telephony/GsmAlphabet;->stringToGsm7BitPackedWithHeader(Ljava/lang/String;[BII)[B
-Lcom/android/internal/telephony/GsmAlphabet;->stringToGsm8BitPacked(Ljava/lang/String;)[B
 Lcom/android/internal/telephony/ICarrierConfigLoader;->getConfigForSubId(ILjava/lang/String;)Landroid/os/PersistableBundle;
 Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
 Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
@@ -2287,67 +2247,13 @@
 Lcom/android/internal/telephony/IWapPushManager;->addPackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
 Lcom/android/internal/telephony/IWapPushManager;->deletePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
 Lcom/android/internal/telephony/IWapPushManager;->updatePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
-Lcom/android/internal/telephony/OperatorInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/OperatorInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/android/internal/telephony/OperatorInfo$State;)V
-Lcom/android/internal/telephony/OperatorInfo;->mOperatorAlphaLong:Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->mOperatorAlphaShort:Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->mOperatorNumeric:Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->mState:Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/OperatorInfo;->rilStateToState(Ljava/lang/String;)Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/SmsAddress;->origBytes:[B
-Lcom/android/internal/telephony/SmsConstants$MessageClass;->CLASS_0:Lcom/android/internal/telephony/SmsConstants$MessageClass;
-Lcom/android/internal/telephony/SmsConstants$MessageClass;->CLASS_1:Lcom/android/internal/telephony/SmsConstants$MessageClass;
-Lcom/android/internal/telephony/SmsConstants$MessageClass;->CLASS_2:Lcom/android/internal/telephony/SmsConstants$MessageClass;
-Lcom/android/internal/telephony/SmsConstants$MessageClass;->CLASS_3:Lcom/android/internal/telephony/SmsConstants$MessageClass;
-Lcom/android/internal/telephony/SmsConstants$MessageClass;->UNKNOWN:Lcom/android/internal/telephony/SmsConstants$MessageClass;
 Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
-Lcom/android/internal/telephony/SmsHeader$ConcatRef;->msgCount:I
-Lcom/android/internal/telephony/SmsHeader$ConcatRef;->refNumber:I
-Lcom/android/internal/telephony/SmsHeader$ConcatRef;->seqNumber:I
 Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
-Lcom/android/internal/telephony/SmsHeader$PortAddrs;->destPort:I
-Lcom/android/internal/telephony/SmsHeader$PortAddrs;->origPort:I
-Lcom/android/internal/telephony/SmsHeader;-><init>()V
-Lcom/android/internal/telephony/SmsHeader;->concatRef:Lcom/android/internal/telephony/SmsHeader$ConcatRef;
-Lcom/android/internal/telephony/SmsHeader;->fromByteArray([B)Lcom/android/internal/telephony/SmsHeader;
-Lcom/android/internal/telephony/SmsHeader;->languageShiftTable:I
-Lcom/android/internal/telephony/SmsHeader;->languageTable:I
-Lcom/android/internal/telephony/SmsHeader;->portAddrs:Lcom/android/internal/telephony/SmsHeader$PortAddrs;
-Lcom/android/internal/telephony/SmsHeader;->toByteArray(Lcom/android/internal/telephony/SmsHeader;)[B
-Lcom/android/internal/telephony/SmsMessageBase$SubmitPduBase;->encodedMessage:[B
-Lcom/android/internal/telephony/SmsMessageBase$SubmitPduBase;->encodedScAddress:[B
 Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
-Lcom/android/internal/telephony/SmsMessageBase;->getDisplayMessageBody()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getDisplayOriginatingAddress()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getMessageBody()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getOriginatingAddress()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getProtocolIdentifier()I
-Lcom/android/internal/telephony/SmsMessageBase;->getPseudoSubject()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getServiceCenterAddress()Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->getStatus()I
-Lcom/android/internal/telephony/SmsMessageBase;->getTimestampMillis()J
-Lcom/android/internal/telephony/SmsMessageBase;->getUserData()[B
-Lcom/android/internal/telephony/SmsMessageBase;->getUserDataHeader()Lcom/android/internal/telephony/SmsHeader;
-Lcom/android/internal/telephony/SmsMessageBase;->isReplace()Z
-Lcom/android/internal/telephony/SmsMessageBase;->isReplyPathPresent()Z
-Lcom/android/internal/telephony/SmsMessageBase;->isStatusReportMessage()Z
-Lcom/android/internal/telephony/SmsMessageBase;->mIsMwi:Z
-Lcom/android/internal/telephony/SmsMessageBase;->mMessageBody:Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->mMessageRef:I
-Lcom/android/internal/telephony/SmsMessageBase;->mMwiDontStore:Z
-Lcom/android/internal/telephony/SmsMessageBase;->mMwiSense:Z
-Lcom/android/internal/telephony/SmsMessageBase;->mOriginatingAddress:Lcom/android/internal/telephony/SmsAddress;
-Lcom/android/internal/telephony/SmsMessageBase;->mPdu:[B
-Lcom/android/internal/telephony/SmsMessageBase;->mScAddress:Ljava/lang/String;
-Lcom/android/internal/telephony/SmsMessageBase;->mUserDataHeader:Lcom/android/internal/telephony/SmsHeader;
-Lcom/android/internal/telephony/SmsRawData;-><init>([B)V
-Lcom/android/internal/telephony/SmsRawData;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/telephony/SmsRawData;->getBytes()[B
 Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
 Lcom/android/internal/view/BaseIWindow;-><init>()V
 Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;->getEnabledInputMethodList()Ljava/util/List;
 Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
 Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession;
 Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 9e6abe4..54cc07a8 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -260,17 +260,7 @@
 Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V
 Lcom/android/internal/R$styleable;->NumberPicker:[I
 Lcom/android/internal/R$styleable;->TwoLineListItem:[I
-Lcom/android/internal/telephony/GsmAlphabet;->gsm7BitPackedToString([BII)Ljava/lang/String;
-Lcom/android/internal/telephony/GsmAlphabet;->stringToGsm7BitPacked(Ljava/lang/String;)[B
 Lcom/android/internal/telephony/ITelephony;->getDataEnabled(I)Z
-Lcom/android/internal/telephony/OperatorInfo$State;->CURRENT:Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/OperatorInfo$State;->FORBIDDEN:Lcom/android/internal/telephony/OperatorInfo$State;
-Lcom/android/internal/telephony/OperatorInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lcom/android/internal/telephony/OperatorInfo;->CREATOR:Landroid/os/Parcelable$Creator;
-Lcom/android/internal/telephony/OperatorInfo;->getOperatorAlphaLong()Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->getOperatorAlphaShort()Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->getOperatorNumeric()Ljava/lang/String;
-Lcom/android/internal/telephony/OperatorInfo;->getState()Lcom/android/internal/telephony/OperatorInfo$State;
 Ljava/lang/System;->arraycopy([BI[BII)V
 Ljava/net/Inet4Address;->ALL:Ljava/net/InetAddress;
 Ljava/net/Inet4Address;->ANY:Ljava/net/InetAddress;
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index c3fae7d..c5d435b 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -58,6 +58,11 @@
     private final ParcelUuid mServiceUuidMask;
 
     @Nullable
+    private final ParcelUuid mServiceSolicitationUuid;
+    @Nullable
+    private final ParcelUuid mServiceSolicitationUuidMask;
+
+    @Nullable
     private final ParcelUuid mServiceDataUuid;
     @Nullable
     private final byte[] mServiceData;
@@ -75,12 +80,15 @@
 
 
     private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
-            ParcelUuid uuidMask, ParcelUuid serviceDataUuid,
+            ParcelUuid uuidMask, ParcelUuid solicitationUuid,
+            ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
             byte[] serviceData, byte[] serviceDataMask,
             int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask) {
         mDeviceName = name;
         mServiceUuid = uuid;
         mServiceUuidMask = uuidMask;
+        mServiceSolicitationUuid = solicitationUuid;
+        mServiceSolicitationUuidMask = solicitationUuidMask;
         mDeviceAddress = deviceAddress;
         mServiceDataUuid = serviceDataUuid;
         mServiceData = serviceData;
@@ -113,6 +121,14 @@
                 dest.writeParcelable(mServiceUuidMask, flags);
             }
         }
+        dest.writeInt(mServiceSolicitationUuid == null ? 0 : 1);
+        if (mServiceSolicitationUuid != null) {
+            dest.writeParcelable(mServiceSolicitationUuid, flags);
+            dest.writeInt(mServiceSolicitationUuidMask == null ? 0 : 1);
+            if (mServiceSolicitationUuidMask != null) {
+                dest.writeParcelable(mServiceSolicitationUuidMask, flags);
+            }
+        }
         dest.writeInt(mServiceDataUuid == null ? 0 : 1);
         if (mServiceDataUuid != null) {
             dest.writeParcelable(mServiceDataUuid, flags);
@@ -172,6 +188,17 @@
                 }
             }
             if (in.readInt() == 1) {
+                ParcelUuid solicitationUuid = in.readParcelable(
+                        ParcelUuid.class.getClassLoader());
+                builder.setServiceSolicitationUuid(solicitationUuid);
+                if (in.readInt() == 1) {
+                    ParcelUuid solicitationUuidMask = in.readParcelable(
+                            ParcelUuid.class.getClassLoader());
+                    builder.setServiceSolicitationUuid(solicitationUuid,
+                            solicitationUuidMask);
+                }
+            }
+            if (in.readInt() == 1) {
                 ParcelUuid servcieDataUuid =
                         in.readParcelable(ParcelUuid.class.getClassLoader());
                 if (in.readInt() == 1) {
@@ -231,6 +258,22 @@
         return mServiceUuidMask;
     }
 
+    /**
+     * Returns the filter set on the service Solicitation uuid.
+     */
+    @Nullable
+    public ParcelUuid getServiceSolicitationUuid() {
+        return mServiceSolicitationUuid;
+    }
+
+    /**
+     * Returns the filter set on the service Solicitation uuid mask.
+     */
+    @Nullable
+    public ParcelUuid getServiceSolicitationUuidMask() {
+        return mServiceSolicitationUuidMask;
+    }
+
     @Nullable
     public String getDeviceAddress() {
         return mDeviceAddress;
@@ -288,7 +331,7 @@
         // Scan record is null but there exist filters on it.
         if (scanRecord == null
                 && (mDeviceName != null || mServiceUuid != null || mManufacturerData != null
-                || mServiceData != null)) {
+                || mServiceData != null || mServiceSolicitationUuid != null)) {
             return false;
         }
 
@@ -303,6 +346,13 @@
             return false;
         }
 
+        // solicitation UUID match.
+        if (mServiceSolicitationUuid != null && !matchesServiceSolicitationUuids(
+                mServiceSolicitationUuid, mServiceSolicitationUuidMask,
+                scanRecord.getServiceSolicitationUuids())) {
+            return false;
+        }
+
         // Service data match
         if (mServiceDataUuid != null) {
             if (!matchesPartialData(mServiceData, mServiceDataMask,
@@ -350,6 +400,36 @@
         return BitUtils.maskedEquals(data, uuid, mask);
     }
 
+    /**
+     * Check if the solicitation uuid pattern is contained in a list of parcel uuids.
+     *
+     */
+    private static boolean matchesServiceSolicitationUuids(ParcelUuid solicitationUuid,
+            ParcelUuid parcelSolicitationUuidMask, List<ParcelUuid> solicitationUuids) {
+        if (solicitationUuid == null) {
+            return true;
+        }
+        if (solicitationUuids == null) {
+            return false;
+        }
+
+        for (ParcelUuid parcelSolicitationUuid : solicitationUuids) {
+            UUID solicitationUuidMask = parcelSolicitationUuidMask == null
+                    ? null : parcelSolicitationUuidMask.getUuid();
+            if (matchesServiceUuid(solicitationUuid.getUuid(), solicitationUuidMask,
+                    parcelSolicitationUuid.getUuid())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // Check if the solicitation uuid pattern matches the particular service solicitation uuid.
+    private static boolean matchesServiceSolicitationUuid(UUID solicitationUuid,
+            UUID solicitationUuidMask, UUID data) {
+        return BitUtils.maskedEquals(data, solicitationUuid, solicitationUuidMask);
+    }
+
     // Check whether the data pattern matches the parsed data.
     private boolean matchesPartialData(byte[] data, byte[] dataMask, byte[] parsedData) {
         if (parsedData == null || parsedData.length < data.length) {
@@ -376,6 +456,8 @@
         return "BluetoothLeScanFilter [mDeviceName=" + mDeviceName + ", mDeviceAddress="
                 + mDeviceAddress
                 + ", mUuid=" + mServiceUuid + ", mUuidMask=" + mServiceUuidMask
+                + ", mServiceSolicitationUuid=" + mServiceSolicitationUuid
+                + ", mServiceSolicitationUuidMask=" + mServiceSolicitationUuidMask
                 + ", mServiceDataUuid=" + Objects.toString(mServiceDataUuid) + ", mServiceData="
                 + Arrays.toString(mServiceData) + ", mServiceDataMask="
                 + Arrays.toString(mServiceDataMask) + ", mManufacturerId=" + mManufacturerId
@@ -391,7 +473,8 @@
                 mServiceDataUuid,
                 Arrays.hashCode(mServiceData),
                 Arrays.hashCode(mServiceDataMask),
-                mServiceUuid, mServiceUuidMask);
+                mServiceUuid, mServiceUuidMask,
+                mServiceSolicitationUuid, mServiceSolicitationUuidMask);
     }
 
     @Override
@@ -412,7 +495,10 @@
                 && Objects.deepEquals(mServiceData, other.mServiceData)
                 && Objects.deepEquals(mServiceDataMask, other.mServiceDataMask)
                 && Objects.equals(mServiceUuid, other.mServiceUuid)
-                && Objects.equals(mServiceUuidMask, other.mServiceUuidMask);
+                && Objects.equals(mServiceUuidMask, other.mServiceUuidMask)
+                && Objects.equals(mServiceSolicitationUuid, other.mServiceSolicitationUuid)
+                && Objects.equals(mServiceSolicitationUuidMask,
+                        other.mServiceSolicitationUuidMask);
     }
 
     /**
@@ -435,6 +521,9 @@
         private ParcelUuid mServiceUuid;
         private ParcelUuid mUuidMask;
 
+        private ParcelUuid mServiceSolicitationUuid;
+        private ParcelUuid mServiceSolicitationUuidMask;
+
         private ParcelUuid mServiceDataUuid;
         private byte[] mServiceData;
         private byte[] mServiceDataMask;
@@ -493,6 +582,36 @@
             return this;
         }
 
+
+        /**
+         * Set filter on service solicitation uuid.
+         */
+        public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid) {
+            mServiceSolicitationUuid = serviceSolicitationUuid;
+            return this;
+        }
+
+
+        /**
+         * Set filter on partial service Solicitation uuid. The {@code SolicitationUuidMask} is the
+         * bit mask for the {@code serviceSolicitationUuid}. Set any bit in the mask to 1 to
+         * indicate a match is needed for the bit in {@code serviceSolicitationUuid}, and 0 to
+         * ignore that bit.
+         *
+         * @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but
+         *             {@code serviceSolicitationUuidMask} is not {@code null}.
+         */
+        public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid,
+                ParcelUuid solicitationUuidMask) {
+            if (mServiceSolicitationUuidMask != null && mServiceSolicitationUuid == null) {
+                throw new IllegalArgumentException(
+                        "SolicitationUuid is null while SolicitationUuidMask is not null!");
+            }
+            mServiceSolicitationUuid = serviceSolicitationUuid;
+            mServiceSolicitationUuidMask = solicitationUuidMask;
+            return this;
+        }
+
         /**
          * Set filtering on service data.
          *
@@ -598,7 +717,8 @@
          */
         public ScanFilter build() {
             return new ScanFilter(mDeviceName, mDeviceAddress,
-                    mServiceUuid, mUuidMask,
+                    mServiceUuid, mUuidMask, mServiceSolicitationUuid,
+                    mServiceSolicitationUuidMask,
                     mServiceDataUuid, mServiceData, mServiceDataMask,
                     mManufacturerId, mManufacturerData, mManufacturerDataMask);
         }
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 07ed18d..7988008 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -51,6 +51,9 @@
     private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16;
     private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20;
     private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21;
+    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT = 0x14;
+    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT = 0x1F;
+    private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15;
     private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
 
     // Flags of the advertising data.
@@ -58,6 +61,8 @@
 
     @Nullable
     private final List<ParcelUuid> mServiceUuids;
+    @Nullable
+    private final List<ParcelUuid> mServiceSolicitationUuids;
 
     private final SparseArray<byte[]> mManufacturerSpecificData;
 
@@ -89,6 +94,15 @@
     }
 
     /**
+     * Returns a list of service solicitation UUIDs within the advertisement that are used to
+     * identify the Bluetooth GATT services.
+     */
+    @Nullable
+    public List<ParcelUuid> getServiceSolicitationUuids() {
+        return mServiceSolicitationUuids;
+    }
+
+    /**
      * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
      * data.
      */
@@ -151,10 +165,12 @@
     }
 
     private ScanRecord(List<ParcelUuid> serviceUuids,
+            List<ParcelUuid> serviceSolicitationUuids,
             SparseArray<byte[]> manufacturerData,
             Map<ParcelUuid, byte[]> serviceData,
             int advertiseFlags, int txPowerLevel,
             String localName, byte[] bytes) {
+        mServiceSolicitationUuids = serviceSolicitationUuids;
         mServiceUuids = serviceUuids;
         mManufacturerSpecificData = manufacturerData;
         mServiceData = serviceData;
@@ -184,6 +200,7 @@
         int currentPos = 0;
         int advertiseFlag = -1;
         List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
+        List<ParcelUuid> serviceSolicitationUuids = new ArrayList<ParcelUuid>();
         String localName = null;
         int txPowerLevel = Integer.MIN_VALUE;
 
@@ -220,6 +237,18 @@
                         parseServiceUuid(scanRecord, currentPos, dataLength,
                                 BluetoothUuid.UUID_BYTES_128_BIT, serviceUuids);
                         break;
+                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_16_BIT:
+                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
+                                BluetoothUuid.UUID_BYTES_16_BIT, serviceSolicitationUuids);
+                        break;
+                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_32_BIT:
+                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
+                                BluetoothUuid.UUID_BYTES_32_BIT, serviceSolicitationUuids);
+                        break;
+                    case DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT:
+                        parseServiceSolicitationUuid(scanRecord, currentPos, dataLength,
+                                BluetoothUuid.UUID_BYTES_128_BIT, serviceSolicitationUuids);
+                        break;
                     case DATA_TYPE_LOCAL_NAME_SHORT:
                     case DATA_TYPE_LOCAL_NAME_COMPLETE:
                         localName = new String(
@@ -265,19 +294,23 @@
             if (serviceUuids.isEmpty()) {
                 serviceUuids = null;
             }
-            return new ScanRecord(serviceUuids, manufacturerData, serviceData,
-                    advertiseFlag, txPowerLevel, localName, scanRecord);
+            if (serviceSolicitationUuids.isEmpty()) {
+                serviceSolicitationUuids = null;
+            }
+            return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData,
+                    serviceData, advertiseFlag, txPowerLevel, localName, scanRecord);
         } catch (Exception e) {
             Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
             // As the record is invalid, ignore all the parsed results for this packet
             // and return an empty record with raw scanRecord bytes in results
-            return new ScanRecord(null, null, null, -1, Integer.MIN_VALUE, null, scanRecord);
+            return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, scanRecord);
         }
     }
 
     @Override
     public String toString() {
         return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
+                + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids
                 + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(
                 mManufacturerSpecificData)
                 + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData)
@@ -297,6 +330,20 @@
         return currentPos;
     }
 
+    /**
+     * Parse service Solicitation UUIDs.
+     */
+    private static int parseServiceSolicitationUuid(byte[] scanRecord, int currentPos,
+            int dataLength, int uuidLength, List<ParcelUuid> serviceSolicitationUuids) {
+        while (dataLength > 0) {
+            byte[] uuidBytes = extractBytes(scanRecord, currentPos, uuidLength);
+            serviceSolicitationUuids.add(BluetoothUuid.parseUuidFrom(uuidBytes));
+            dataLength -= uuidLength;
+            currentPos += uuidLength;
+        }
+        return currentPos;
+    }
+
     // Helper method to extract bytes from byte array.
     private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
         byte[] bytes = new byte[length];
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 085d77d..f5339ef 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -236,9 +236,15 @@
                 // However, the caller may be expecting to access them my index. Hence,
                 // we have to execute the query as if allowed to get a cursor with the
                 // columns. We then use the column names to return an empty cursor.
-                Cursor cursor = ContentProvider.this.query(
-                        uri, projection, queryArgs,
-                        CancellationSignal.fromTransport(cancellationSignal));
+                Cursor cursor;
+                final String original = setCallingPackage(callingPkg);
+                try {
+                    cursor = ContentProvider.this.query(
+                            uri, projection, queryArgs,
+                            CancellationSignal.fromTransport(cancellationSignal));
+                } finally {
+                    setCallingPackage(original);
+                }
                 if (cursor == null) {
                     return null;
                 }
@@ -260,6 +266,7 @@
 
         @Override
         public String getType(Uri uri) {
+            // getCallingPackage() isn't available in getType(), as the javadoc states.
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
@@ -276,7 +283,12 @@
             int userId = getUserIdFromUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
-                return rejectInsert(uri, initialValues);
+                final String original = setCallingPackage(callingPkg);
+                try {
+                    return rejectInsert(uri, initialValues);
+                } finally {
+                    setCallingPackage(original);
+                }
             }
             Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
             final String original = setCallingPackage(callingPkg);
@@ -440,6 +452,7 @@
 
         @Override
         public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+            // getCallingPackage() isn't available in getType(), as the javadoc states.
             validateIncomingUri(uri);
             uri = maybeGetUriWithoutUserId(uri);
             Trace.traceBegin(TRACE_TAG_DATABASE, "getStreamTypes");
diff --git a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
index 06c069c..8ea1db2 100644
--- a/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
+++ b/core/java/android/database/sqlite/SQLiteCompatibilityWalFlags.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.app.Application;
 import android.provider.Settings;
@@ -33,6 +34,7 @@
  * for consistent behavior across all connections opened in the process.
  * @hide
  */
+@TestApi
 public class SQLiteCompatibilityWalFlags {
 
     private static final String TAG = "SQLiteCompatibilityWalFlags";
@@ -45,6 +47,9 @@
     // This flag is used to avoid recursive initialization due to circular dependency on Settings
     private static volatile boolean sCallingGlobalSettings;
 
+    private SQLiteCompatibilityWalFlags() {
+    }
+
     /**
      * @hide
      */
@@ -140,6 +145,7 @@
      * @hide
      */
     @VisibleForTesting
+    @TestApi
     public static void reset() {
         sInitialized = false;
         sFlagsSet = false;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index fb916d3..ce18796 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3840,7 +3840,7 @@
     @UnsupportedAppUsage
     public static boolean setProcessDefaultNetworkForHostResolution(Network network) {
         return NetworkUtils.bindProcessToNetworkForHostResolution(
-                network == null ? NETID_UNSET : network.netId);
+                (network == null) ? NETID_UNSET : network.getNetIdForResolv());
     }
 
     /**
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 142023d..bf2344d 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -100,21 +100,29 @@
     // anytime and (b) receivers should be explicit about attempts to bypass
     // Private DNS so that the intent of the code is easily determined and
     // code search audits are possible.
-    private boolean mPrivateDnsBypass = false;
+    private final transient boolean mPrivateDnsBypass;
 
     /**
      * @hide
      */
     @UnsupportedAppUsage
     public Network(int netId) {
+        this(netId, false);
+    }
+
+    /**
+     * @hide
+     */
+    public Network(int netId, boolean privateDnsBypass) {
         this.netId = netId;
+        this.mPrivateDnsBypass = privateDnsBypass;
     }
 
     /**
      * @hide
      */
     public Network(Network that) {
-        this.netId = that.netId;
+        this(that.netId, that.mPrivateDnsBypass);
     }
 
     /**
@@ -133,8 +141,7 @@
      * Operates the same as {@code InetAddress.getByName} except that host
      * resolution is done on this network.
      *
-     * @param host
-     *            the hostName to be resolved to an address or {@code null}.
+     * @param host the hostname to be resolved to an address or {@code null}.
      * @return the {@code InetAddress} instance representing the host.
      * @throws UnknownHostException
      *             if the address lookup fails.
@@ -144,14 +151,14 @@
     }
 
     /**
-     * Specify whether or not Private DNS should be bypassed when attempting
+     * Obtain a Network object for which Private DNS is to be bypassed when attempting
      * to use {@link #getAllByName(String)}/{@link #getByName(String)} methods on the given
      * instance for hostname resolution.
      *
      * @hide
      */
-    public void setPrivateDnsBypass(boolean bypass) {
-        mPrivateDnsBypass = bypass;
+    public Network getPrivateDnsBypassingCopy() {
+        return new Network(netId, true);
     }
 
     /**
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 10c0ce2..b8d7cf1 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -85,19 +85,16 @@
      * @return true if the transaction was successful.
      */
     public boolean requestTime(String host, int timeout, Network network) {
-        // This flag only affects DNS resolution and not other socket semantics,
-        // therefore it's safe to set unilaterally rather than take more
-        // defensive measures like making a copy.
-        network.setPrivateDnsBypass(true);
+        final Network networkForResolv = network.getPrivateDnsBypassingCopy();
         InetAddress address = null;
         try {
-            address = network.getByName(host);
+            address = networkForResolv.getByName(host);
         } catch (Exception e) {
             EventLogTags.writeNtpFailure(host, e.toString());
             if (DBG) Log.d(TAG, "request time failed: " + e);
             return false;
         }
-        return requestTime(address, NTP_PORT, timeout, network);
+        return requestTime(address, NTP_PORT, timeout, networkForResolv);
     }
 
     public boolean requestTime(InetAddress address, int port, int timeout, Network network) {
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index a463afa..22dd4fc 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -139,6 +139,8 @@
     public static final int TAG_SYSTEM_GPS = 0xFFFFFF44;
     /** @hide */
     public static final int TAG_SYSTEM_PAC = 0xFFFFFF45;
+    /** @hide */
+    public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46;
 
     private static INetworkStatsService sStatsService;
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 7e7666a..cc6bb12 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -846,11 +846,19 @@
             return;
         }
         Set<Map.Entry<String,Object>> entries = val.entrySet();
-        writeInt(entries.size());
+        int size = entries.size();
+        writeInt(size);
+
         for (Map.Entry<String,Object> e : entries) {
             writeValue(e.getKey());
             writeValue(e.getValue());
+            size--;
         }
+
+        if (size != 0) {
+            throw new BadParcelableException("Map size does not match number of entries!");
+        }
+
     }
 
     /**
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 59ea28f..d4d3dc8 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -120,15 +120,6 @@
         mStorage.write(bytes, 0, bytes.length);
     }
 
-    /**
-     * Adds a boolean by adding either a 1 or 0 to the output.
-     */
-    public void writeBoolean(boolean val) {
-        int toWrite = val ? 1 : 0;
-        mStorage.write(EVENT_TYPE_INT);
-        write4Bytes(toWrite);
-    }
-
     private StatsLogEventWrapper(Parcel in) {
         readFromParcel(in);
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bffed8d..7df42eb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9556,6 +9556,17 @@
         public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
 
         /**
+         * Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
+         *
+         * Integer values are interpreted as boolean, and the absence of an explicit setting
+         * is interpreted as |true|.
+         * TODO: make the default |false|
+         * @hide
+         */
+        public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
+                "tether_enable_legacy_dhcp_server";
+
+        /**
          * List of certificate (hex string representation of the application's certificate - SHA-1
          * or SHA-256) and carrier app package pairs which are whitelisted to prompt the user for
          * install when a sim card with matching UICC carrier privilege rules is inserted.  The
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
index e5e1c92..1cd76d2 100644
--- a/core/java/android/service/autofill/AutofillFieldClassificationService.java
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -65,36 +65,16 @@
     /**
      * Manifest metadata key for the resource string containing the name of the default field
      * classification algorithm.
-     *
-     * @deprecated Use {@link #RESOURCE_DEFAULT_ALGORITHM} instead.
      */
-    @Deprecated
     public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM =
             "android.autofill.field_classification.default_algorithm";
-
     /**
      * Manifest metadata key for the resource string array containing the names of all field
      * classification algorithms provided by the service.
-     *
-     * @deprecated Use {@link #RESOURCE_AVAILABLE_ALGORITHMS} instead.
      */
-    @Deprecated
     public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
             "android.autofill.field_classification.available_algorithms";
 
-    /**
-     * Name of the resource string containing the name of the default field
-     * classification algorithm.
-     */
-    public static final String RESOURCE_DEFAULT_ALGORITHM =
-            "autofill_field_classification_default_algorithm";
-
-   /**
-    * Name of the resource string array containing the names of all field
-    * classification algorithms provided by the service.
-    */
-    public static final String RESOURCE_AVAILABLE_ALGORITHMS =
-            "autofill_field_classification_available_algorithms";
 
     /** {@hide} **/
     public static final String EXTRA_SCORES = "scores";
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 4bd6e5c..1d0c987 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -123,6 +123,10 @@
 
     /**
      * Gets the contexts associated with each previous fill request.
+     *
+     * <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
+     * include contexts from requests whose {@link SaveInfo} had the
+     * {@link SaveInfo#FLAG_DELAY_SAVE} flag.
      */
     public @NonNull List<FillContext> getFillContexts() {
         return mContexts;
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index b845250..f571956 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -246,7 +246,7 @@
      * multiple screens to implement an autofillable workflow (for example, one screen for the
      * username field, another for password).
      */
-    // TODO(b/112051762): improve documentation: add example, document relationship with other
+    // TODO(b/113281366): improve documentation: add example, document relationship with other
     // flagss, etc...
     public static final int FLAG_DELAY_SAVE = 0x4;
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07f74f0..d0795c9 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -11725,7 +11725,6 @@
                         Slog.d(TAG, "UID=" + uid + " rx_bytes=" + rxBytes + " rx_time=" + timeRxMs);
                     }
                     counter.getRxTimeCounter().addCountLocked(timeRxMs);
-                    leftOverRxTimeMs -= timeRxMs;
                 }
 
                 if (totalTxBytes > 0 && txBytes > 0) {
@@ -11734,7 +11733,6 @@
                         Slog.d(TAG, "UID=" + uid + " tx_bytes=" + txBytes + " tx_time=" + timeTxMs);
                     }
                     counter.getTxTimeCounters()[0].addCountLocked(timeTxMs);
-                    leftOverTxTimeMs -= timeTxMs;
                 }
             }
         }
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 3fcedd0..6ebf35c 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -22,8 +22,6 @@
 #include "SkColorFilter.h"
 #include "SkColorMatrixFilter.h"
 
-#include <Caches.h>
-
 namespace android {
 
 using namespace uirenderer;
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index f8bb77a..755fcfb 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -20,7 +20,6 @@
 #include "SkMatrix.h"
 #include "core_jni_helpers.h"
 
-#include <Caches.h>
 #include <jni.h>
 
 namespace android {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index cff7720..68f5bef 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -6,7 +6,6 @@
 #include "SkBlendMode.h"
 #include "core_jni_helpers.h"
 
-#include <Caches.h>
 #include <jni.h>
 
 using namespace android::uirenderer;
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index d098a35..3e464c6 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -36,6 +36,7 @@
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
+#include "surfacetexture/SurfaceTexture.h"
 
 // ----------------------------------------------------------------------------
 
@@ -80,10 +81,10 @@
 // ----------------------------------------------------------------------------
 
 static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
-        const sp<GLConsumer>& surfaceTexture)
+        const sp<SurfaceTexture>& surfaceTexture)
 {
-    GLConsumer* const p =
-        (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
+    SurfaceTexture* const p =
+        (SurfaceTexture*)env->GetLongField(thiz, fields.surfaceTexture);
     if (surfaceTexture.get()) {
         surfaceTexture->incStrong((void*)SurfaceTexture_setSurfaceTexture);
     }
@@ -108,10 +109,10 @@
 }
 
 static void SurfaceTexture_setFrameAvailableListener(JNIEnv* env,
-        jobject thiz, sp<GLConsumer::FrameAvailableListener> listener)
+        jobject thiz, sp<SurfaceTexture::FrameAvailableListener> listener)
 {
-    GLConsumer::FrameAvailableListener* const p =
-        (GLConsumer::FrameAvailableListener*)
+    SurfaceTexture::FrameAvailableListener* const p =
+        (SurfaceTexture::FrameAvailableListener*)
             env->GetLongField(thiz, fields.frameAvailableListener);
     if (listener.get()) {
         listener->incStrong((void*)SurfaceTexture_setSurfaceTexture);
@@ -122,8 +123,8 @@
     env->SetLongField(thiz, fields.frameAvailableListener, (jlong)listener.get());
 }
 
-sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
-    return (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture);
+sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) {
+    return (SurfaceTexture*)env->GetLongField(thiz, fields.surfaceTexture);
 }
 
 sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) {
@@ -131,7 +132,7 @@
 }
 
 sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz) {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, thiz));
     sp<Surface> surfaceTextureClient(surfaceTexture != NULL ? new Surface(producer) : NULL);
     return surfaceTextureClient;
@@ -144,7 +145,7 @@
 
 // ----------------------------------------------------------------------------
 
-class JNISurfaceTextureContext : public GLConsumer::FrameAvailableListener
+class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener
 {
 public:
     JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
@@ -266,12 +267,12 @@
         consumer->setMaxBufferCount(1);
     }
 
-    sp<GLConsumer> surfaceTexture;
+    sp<SurfaceTexture> surfaceTexture;
     if (isDetached) {
-        surfaceTexture = new GLConsumer(consumer, GL_TEXTURE_EXTERNAL_OES,
+        surfaceTexture = new SurfaceTexture(consumer, GL_TEXTURE_EXTERNAL_OES,
                 true, !singleBufferMode);
     } else {
-        surfaceTexture = new GLConsumer(consumer, texName,
+        surfaceTexture = new SurfaceTexture(consumer, texName,
                 GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode);
     }
 
@@ -306,7 +307,7 @@
 
 static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->setFrameAvailableListener(0);
     SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
     SurfaceTexture_setSurfaceTexture(env, thiz, 0);
@@ -315,13 +316,13 @@
 
 static void SurfaceTexture_setDefaultBufferSize(
         JNIEnv* env, jobject thiz, jint width, jint height) {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->setDefaultBufferSize(width, height);
 }
 
 static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     status_t err = surfaceTexture->updateTexImage();
     if (err == INVALID_OPERATION) {
         jniThrowException(env, IllegalStateException, "Unable to update texture contents (see "
@@ -333,7 +334,7 @@
 
 static void SurfaceTexture_releaseTexImage(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     status_t err = surfaceTexture->releaseTexImage();
     if (err == INVALID_OPERATION) {
         jniThrowException(env, IllegalStateException, "Unable to release texture contents (see "
@@ -345,20 +346,20 @@
 
 static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->detachFromContext();
 }
 
 static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->attachToContext((GLuint)tex);
 }
 
 static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
         jfloatArray jmtx)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     float* mtx = env->GetFloatArrayElements(jmtx, NULL);
     surfaceTexture->getTransformMatrix(mtx);
     env->ReleaseFloatArrayElements(jmtx, mtx, 0);
@@ -366,19 +367,19 @@
 
 static jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->getTimestamp();
 }
 
 static void SurfaceTexture_release(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->abandon();
 }
 
 static jboolean SurfaceTexture_isReleased(JNIEnv* env, jobject thiz)
 {
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     return surfaceTexture->isAbandoned();
 }
 
diff --git a/core/jni/android_view_TextureLayer.cpp b/core/jni/android_view_TextureLayer.cpp
index d3a447f..1ccb6a8 100644
--- a/core/jni/android_view_TextureLayer.cpp
+++ b/core/jni/android_view_TextureLayer.cpp
@@ -67,8 +67,7 @@
 static void TextureLayer_setSurfaceTexture(JNIEnv* env, jobject clazz,
         jlong layerUpdaterPtr, jobject surface) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
-    sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
-    layer->setSurfaceTexture(surfaceTexture);
+    layer->setSurfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
 }
 
 static void TextureLayer_updateSurfaceTexture(JNIEnv* env, jobject clazz,
diff --git a/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h b/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
index c534d4b..0ad2587 100644
--- a/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
+++ b/core/jni/include/android_runtime/android_graphics_SurfaceTexture.h
@@ -23,14 +23,14 @@
 
 namespace android {
 
-class GLConsumer;
 class IGraphicBufferProducer;
+class SurfaceTexture;
 
 extern sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz);
 extern bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
 
-/* Gets the underlying GLConsumer from a SurfaceTexture Java object. */
-extern sp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
+/* Gets the underlying C++ SurfaceTexture object from a SurfaceTexture Java object. */
+extern sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
 
 /* gets the producer end of the SurfaceTexture */
 extern sp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 289c898..836e824 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3498,6 +3498,9 @@
          empty string is passed in -->
     <string name="config_wlan_network_service_package" translatable="false"></string>
 
+    <!-- Telephony qualified networks service package name to bind to by default. -->
+    <string name="config_qualified_networks_service_package" translatable="false"></string>
+
     <!-- Wear devices: Controls the radios affected by Activity Mode. -->
     <string-array name="config_wearActivityModeRadios">
         <item>"wifi"</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5358830..8ac2474 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -273,6 +273,7 @@
   <java-symbol type="string" name="config_wlan_network_service_package" />
   <java-symbol type="string" name="config_wwan_data_service_package" />
   <java-symbol type="string" name="config_wlan_data_service_package" />
+  <java-symbol type="string" name="config_qualified_networks_service_package" />
   <java-symbol type="bool" name="config_networkSamplingWakesDevice" />
   <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
   <java-symbol type="bool" name="config_sip_wifi_only" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 71627ab..189a4aa 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -422,6 +422,7 @@
                     Settings.Global.TETHER_DUN_REQUIRED,
                     Settings.Global.TETHER_OFFLOAD_DISABLED,
                     Settings.Global.TETHER_SUPPORTED,
+                    Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER,
                     Settings.Global.TEXT_CLASSIFIER_CONSTANTS,
                     Settings.Global.THEATER_MODE_ON,
                     Settings.Global.TIME_ONLY_MODE_CONSTANTS,
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 3d2a271..bd497c1 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -29,6 +29,7 @@
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.ArraySet;
 
 import java.io.ByteArrayInputStream;
@@ -128,14 +129,14 @@
     @NonNull public static KeymasterArguments prepareAttestationArgumentsIfMisprovisioned(
             Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
             DeviceIdAttestationException {
-        if (!isPotentiallyMisprovisionedDevice(context)) {
-            return null;
-        }
         Resources resources = context.getResources();
         String misprovisionedBrand = resources.getString(
                 com.android.internal.R.string.config_misprovisionedBrandValue);
+        if (!TextUtils.isEmpty(misprovisionedBrand) && !isPotentiallyMisprovisionedDevice(context)){
+            return null;
+        }
         return prepareAttestationArguments(
-                    context, idTypes, attestationChallenge, misprovisionedBrand);
+                context, idTypes, attestationChallenge, misprovisionedBrand);
     }
 
     @NonNull private static boolean isPotentiallyMisprovisionedDevice(Context context) {
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 83e90b6..62ab790 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -175,9 +175,7 @@
         "pipeline/skia/SkiaRecordingCanvas.cpp",
         "pipeline/skia/SkiaVulkanPipeline.cpp",
         "pipeline/skia/VectorDrawableAtlas.cpp",
-        "renderstate/PixelBufferState.cpp",
         "renderstate/RenderState.cpp",
-        "renderstate/TextureState.cpp",
         "renderthread/CacheManager.cpp",
         "renderthread/CanvasContext.cpp",
         "renderthread/DrawFrameTask.cpp",
@@ -189,6 +187,9 @@
         "renderthread/TimeLord.cpp",
         "renderthread/Frame.cpp",
         "service/GraphicsStatsService.cpp",
+        "surfacetexture/EGLConsumer.cpp",
+        "surfacetexture/ImageConsumer.cpp",
+        "surfacetexture/SurfaceTexture.cpp",
         "thread/TaskManager.cpp",
         "utils/Blur.cpp",
         "utils/Color.cpp",
@@ -200,7 +201,6 @@
         "AnimationContext.cpp",
         "Animator.cpp",
         "AnimatorManager.cpp",
-        "Caches.cpp",
         "CanvasState.cpp",
         "CanvasTransform.cpp",
         "ClipArea.cpp",
@@ -209,7 +209,6 @@
         "DeviceInfo.cpp",
         "FrameInfo.cpp",
         "FrameInfoVisualizer.cpp",
-        "GlLayer.cpp",
         "GpuMemoryTracker.cpp",
         "HardwareBitmapUploader.cpp",
         "Interpolator.cpp",
@@ -219,7 +218,6 @@
         "Matrix.cpp",
         "EglReadback.cpp",
         "PathParser.cpp",
-        "PixelBuffer.cpp",
         "ProfileData.cpp",
         "ProfileDataContainer.cpp",
         "Properties.cpp",
@@ -230,9 +228,7 @@
         "ResourceCache.cpp",
         "SkiaCanvas.cpp",
         "Snapshot.cpp",
-        "Texture.cpp",
         "VectorDrawable.cpp",
-        "VkLayer.cpp",
         "protos/graphicsstats.proto",
     ],
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
deleted file mode 100644
index 2541444..0000000
--- a/libs/hwui/Caches.cpp
+++ /dev/null
@@ -1,103 +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.
- */
-
-#include "Caches.h"
-
-#include "GlLayer.h"
-#include "Properties.h"
-#include "renderstate/RenderState.h"
-#include "utils/GLUtils.h"
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-namespace android {
-namespace uirenderer {
-
-Caches* Caches::sInstance = nullptr;
-
-///////////////////////////////////////////////////////////////////////////////
-// Macros
-///////////////////////////////////////////////////////////////////////////////
-
-#if DEBUG_CACHE_FLUSH
-#define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
-#else
-#define FLUSH_LOGD(...)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors/destructor
-///////////////////////////////////////////////////////////////////////////////
-
-Caches::Caches(RenderState& renderState) : mInitialized(false) {
-    INIT_LOGD("Creating OpenGL renderer caches");
-    init();
-    initStaticProperties();
-}
-
-bool Caches::init() {
-    if (mInitialized) return false;
-
-    ATRACE_NAME("Caches::init");
-
-    mRegionMesh = nullptr;
-
-    mInitialized = true;
-
-    mPixelBufferState = new PixelBufferState();
-    mTextureState = new TextureState();
-    mTextureState->constructTexture(*this);
-
-    return true;
-}
-
-void Caches::initStaticProperties() {
-    // OpenGL ES 3.0+ specific features
-    gpuPixelBuffersEnabled = extensions().hasPixelBufferObjects() &&
-                             property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
-}
-
-void Caches::terminate() {
-    if (!mInitialized) return;
-    mRegionMesh.reset(nullptr);
-
-    clearGarbage();
-
-    delete mPixelBufferState;
-    mPixelBufferState = nullptr;
-    delete mTextureState;
-    mTextureState = nullptr;
-    mInitialized = false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Memory management
-///////////////////////////////////////////////////////////////////////////////
-
-void Caches::clearGarbage() {}
-
-void Caches::flush(FlushMode mode) {
-    clearGarbage();
-    glFinish();
-    // Errors during cleanup should be considered non-fatal, dump them and
-    // and move on. TODO: All errors or just errors like bad surface?
-    GLUtils::dumpGLErrors();
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
deleted file mode 100644
index 642f9dc..0000000
--- a/libs/hwui/Caches.h
+++ /dev/null
@@ -1,135 +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.
- */
-
-#pragma once
-
-#include "DeviceInfo.h"
-#include "Extensions.h"
-#include "ResourceCache.h"
-#include "renderstate/PixelBufferState.h"
-#include "renderstate/TextureState.h"
-#include "thread/TaskManager.h"
-#include "thread/TaskProcessor.h"
-
-#include <memory>
-#include <vector>
-
-#include <GLES3/gl3.h>
-
-#include <utils/KeyedVector.h>
-
-#include <cutils/compiler.h>
-
-#include <SkPath.h>
-
-#include <vector>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Caches
-///////////////////////////////////////////////////////////////////////////////
-
-class RenderNode;
-class RenderState;
-
-class ANDROID_API Caches {
-public:
-    static Caches& createInstance(RenderState& renderState) {
-        LOG_ALWAYS_FATAL_IF(sInstance, "double create of Caches attempted");
-        sInstance = new Caches(renderState);
-        return *sInstance;
-    }
-
-    static Caches& getInstance() {
-        LOG_ALWAYS_FATAL_IF(!sInstance, "instance not yet created");
-        return *sInstance;
-    }
-
-    static bool hasInstance() { return sInstance != nullptr; }
-
-private:
-    explicit Caches(RenderState& renderState);
-    static Caches* sInstance;
-
-public:
-    enum class FlushMode { Layers = 0, Moderate, Full };
-
-    /**
-     * Initialize caches.
-     */
-    bool init();
-
-    bool isInitialized() { return mInitialized; }
-
-    /**
-     * Flush the cache.
-     *
-     * @param mode Indicates how much of the cache should be flushed
-     */
-    void flush(FlushMode mode);
-
-    /**
-     * Destroys all resources associated with this cache. This should
-     * be called after a flush(FlushMode::Full).
-     */
-    void terminate();
-
-    /**
-     * Call this on each frame to ensure that garbage is deleted from
-     * GPU memory.
-     */
-    void clearGarbage();
-
-    /**
-     * Returns the GL RGBA internal format to use for the current device
-     * If the device supports linear blending and needSRGB is true,
-     * this function returns GL_SRGB8_ALPHA8, otherwise it returns GL_RGBA
-     */
-    constexpr GLint rgbaInternalFormat(bool needSRGB = true) const {
-        return extensions().hasLinearBlending() && needSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA;
-    }
-
-public:
-    TaskManager tasks;
-
-    bool gpuPixelBuffersEnabled;
-
-    const Extensions& extensions() const { return DeviceInfo::get()->extensions(); }
-    PixelBufferState& pixelBufferState() { return *mPixelBufferState; }
-    TextureState& textureState() { return *mTextureState; }
-
-private:
-    void initStaticProperties();
-
-    static void eventMarkNull(GLsizei length, const GLchar* marker) {}
-    static void startMarkNull(GLsizei length, const GLchar* marker) {}
-    static void endMarkNull() {}
-
-    // Used to render layers
-    std::unique_ptr<TextureVertex[]> mRegionMesh;
-
-    bool mInitialized;
-
-    // TODO: move below to RenderState
-    PixelBufferState* mPixelBufferState = nullptr;
-    TextureState* mTextureState = nullptr;
-
-};  // class Caches
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 569de76..0091655 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -15,27 +15,20 @@
  */
 #include "DeferredLayerUpdater.h"
 
-#include "GlLayer.h"
-#include "VkLayer.h"
 #include "renderstate/RenderState.h"
-#include "renderthread/EglManager.h"
-#include "renderthread/RenderTask.h"
 #include "utils/PaintUtils.h"
 
 namespace android {
 namespace uirenderer {
 
-DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
-                                           Layer::Api layerApi)
+DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
         : mRenderState(renderState)
         , mBlend(false)
         , mSurfaceTexture(nullptr)
         , mTransform(nullptr)
         , mGLContextAttached(false)
         , mUpdateTexImage(false)
-        , mLayer(nullptr)
-        , mLayerApi(layerApi)
-        , mCreateLayerFn(createLayerFn) {
+        , mLayer(nullptr) {
     renderState.registerDeferredLayerUpdater(this);
 }
 
@@ -50,13 +43,9 @@
         return;
     }
 
-    if (mSurfaceTexture.get() && mLayerApi == Layer::Api::OpenGL && mGLContextAttached) {
-        status_t err = mSurfaceTexture->detachFromContext();
+    if (mSurfaceTexture.get() && mGLContextAttached) {
+        mSurfaceTexture->detachFromView();
         mGLContextAttached = false;
-        if (err != 0) {
-            // TODO: Elevate to fatal exception
-            ALOGE("Failed to detach SurfaceTexture from context %d", err);
-        }
     }
 
     mLayer->postDecStrong();
@@ -75,99 +64,53 @@
 
 void DeferredLayerUpdater::apply() {
     if (!mLayer) {
-        mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
+        mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
     }
 
     mLayer->setColorFilter(mColorFilter);
     mLayer->setAlpha(mAlpha, mMode);
 
     if (mSurfaceTexture.get()) {
-        if (mLayer->getApi() == Layer::Api::Vulkan) {
-            if (mUpdateTexImage) {
-                mUpdateTexImage = false;
-                doUpdateVkTexImage();
-            }
-        } else {
-            LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                                "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
-                                mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
-            if (!mGLContextAttached) {
-                mGLContextAttached = true;
-                mUpdateTexImage = true;
-                mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
-            }
-            if (mUpdateTexImage) {
-                mUpdateTexImage = false;
-                doUpdateTexImage();
-            }
-            GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
-            static_cast<GlLayer*>(mLayer)->setRenderTarget(renderTarget);
+        if (!mGLContextAttached) {
+            mGLContextAttached = true;
+            mUpdateTexImage = true;
+            mSurfaceTexture->attachToView();
         }
+        if (mUpdateTexImage) {
+            mUpdateTexImage = false;
+            sk_sp<SkImage> layerImage;
+            SkMatrix textureTransform;
+            android_dataspace dataSpace;
+            bool queueEmpty = true;
+            // If the SurfaceTexture queue is in synchronous mode, need to discard all
+            // but latest frame. Since we can't tell which mode it is in,
+            // do this unconditionally.
+            do {
+                layerImage = mSurfaceTexture->dequeueImage(textureTransform, dataSpace, &queueEmpty,
+                        mRenderState);
+            } while (layerImage.get() && (!queueEmpty));
+            if (layerImage.get()) {
+                // force filtration if buffer size != layer size
+                bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
+                updateLayer(forceFilter, textureTransform, dataSpace, layerImage);
+            }
+        }
+
         if (mTransform) {
-            mLayer->getTransform().load(*mTransform);
+            mLayer->getTransform() = *mTransform;
             setTransform(nullptr);
         }
     }
 }
 
-void DeferredLayerUpdater::doUpdateTexImage() {
-    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
-                        "doUpdateTexImage non GL backend %x, GL %x, VK %x", mLayer->getApi(),
-                        Layer::Api::OpenGL, Layer::Api::Vulkan);
-    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
-        float transform[16];
-
-        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
-        // If the GLConsumer queue is in synchronous mode, need to discard all
-        // but latest frame, using the frame number to tell when we no longer
-        // have newer frames to target. Since we can't tell which mode it is in,
-        // do this unconditionally.
-        int dropCounter = 0;
-        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
-            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
-            if (newFrameNumber == frameNumber) break;
-            frameNumber = newFrameNumber;
-            dropCounter++;
-        }
-
-        bool forceFilter = false;
-        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
-        if (buffer != nullptr) {
-            // force filtration if buffer size != layer size
-            forceFilter = mWidth != static_cast<int>(buffer->getWidth()) ||
-                          mHeight != static_cast<int>(buffer->getHeight());
-        }
-
-#if DEBUG_RENDERER
-        if (dropCounter > 0) {
-            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
-        }
-#endif
-        mSurfaceTexture->getTransformMatrix(transform);
-
-        updateLayer(forceFilter, transform, mSurfaceTexture->getCurrentDataSpace());
-    }
-}
-
-void DeferredLayerUpdater::doUpdateVkTexImage() {
-    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
-                        "updateLayer non Vulkan backend %x, GL %x, VK %x", mLayer->getApi(),
-                        Layer::Api::OpenGL, Layer::Api::Vulkan);
-
-    static const mat4 identityMatrix;
-    updateLayer(false, identityMatrix.data, HAL_DATASPACE_UNKNOWN);
-
-    VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
-    vkLayer->updateTexture();
-}
-
-void DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform,
-                                       android_dataspace dataspace) {
+void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
+        android_dataspace dataspace, const sk_sp<SkImage>& layerImage) {
     mLayer->setBlend(mBlend);
     mLayer->setForceFilter(forceFilter);
     mLayer->setSize(mWidth, mHeight);
-    mLayer->getTexTransform().load(textureTransform);
+    mLayer->getTexTransform() = textureTransform;
     mLayer->setDataSpace(dataspace);
+    mLayer->setImage(layerImage);
 }
 
 void DeferredLayerUpdater::detachSurfaceTexture() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index fe3ee7a..4c323b8 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -17,18 +17,19 @@
 #pragma once
 
 #include <SkColorFilter.h>
+#include <SkImage.h>
 #include <SkMatrix.h>
 #include <cutils/compiler.h>
-#include <gui/GLConsumer.h>
+#include <map>
 #include <system/graphics.h>
 #include <utils/StrongPointer.h>
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include "surfacetexture/SurfaceTexture.h"
 #include "Layer.h"
 #include "Rect.h"
-#include "renderthread/RenderThread.h"
 
 namespace android {
 namespace uirenderer {
@@ -41,12 +42,7 @@
 public:
     // Note that DeferredLayerUpdater assumes it is taking ownership of the layer
     // and will not call incrementRef on it as a result.
-    typedef std::function<Layer*(RenderState& renderState, uint32_t layerWidth,
-                                 uint32_t layerHeight, sk_sp<SkColorFilter> colorFilter, int alpha,
-                                 SkBlendMode mode, bool blend)>
-            CreateLayerFn;
-    ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
-                                              Layer::Api layerApi);
+    ANDROID_API explicit DeferredLayerUpdater(RenderState& renderState);
 
     ANDROID_API ~DeferredLayerUpdater();
 
@@ -70,13 +66,13 @@
         return false;
     }
 
-    ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture) {
-        if (texture.get() != mSurfaceTexture.get()) {
-            mSurfaceTexture = texture;
+    ANDROID_API void setSurfaceTexture(const sp<SurfaceTexture>& consumer) {
+        if (consumer.get() != mSurfaceTexture.get()) {
+            mSurfaceTexture = consumer;
 
-            GLenum target = texture->getCurrentTextureTarget();
+            GLenum target = consumer->getCurrentTextureTarget();
             LOG_ALWAYS_FATAL_IF(target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES,
-                                "set unsupported GLConsumer with target %x", target);
+                                "set unsupported SurfaceTexture with target %x", target);
         }
     }
 
@@ -97,12 +93,11 @@
 
     void detachSurfaceTexture();
 
-    void updateLayer(bool forceFilter, const float* textureTransform, android_dataspace dataspace);
+    void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
+            android_dataspace dataspace, const sk_sp<SkImage>& layerImage);
 
     void destroyLayer();
 
-    Layer::Api getBackingLayerApi() { return mLayerApi; }
-
 private:
     RenderState& mRenderState;
 
@@ -113,17 +108,12 @@
     sk_sp<SkColorFilter> mColorFilter;
     int mAlpha = 255;
     SkBlendMode mMode = SkBlendMode::kSrcOver;
-    sp<GLConsumer> mSurfaceTexture;
+    sp<SurfaceTexture> mSurfaceTexture;
     SkMatrix* mTransform;
     bool mGLContextAttached;
     bool mUpdateTexImage;
 
     Layer* mLayer;
-    Layer::Api mLayerApi;
-    CreateLayerFn mCreateLayerFn;
-
-    void doUpdateTexImage();
-    void doUpdateVkTexImage();
 };
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/GlLayer.cpp b/libs/hwui/GlLayer.cpp
deleted file mode 100644
index 432bb85..0000000
--- a/libs/hwui/GlLayer.cpp
+++ /dev/null
@@ -1,68 +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.
- */
-
-#include "GlLayer.h"
-
-#include "Caches.h"
-#include "RenderNode.h"
-#include "renderstate/RenderState.h"
-
-namespace android {
-namespace uirenderer {
-
-GlLayer::GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                 sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
-        : Layer(renderState, Api::OpenGL, colorFilter, alpha, mode)
-        , caches(Caches::getInstance())
-        , texture(caches) {
-    texture.mWidth = layerWidth;
-    texture.mHeight = layerHeight;
-    texture.blend = blend;
-}
-
-GlLayer::~GlLayer() {
-    // There's a rare possibility that Caches could have been destroyed already
-    // since this method is queued up as a task.
-    // Since this is a reset method, treat this as non-fatal.
-    if (caches.isInitialized() && texture.mId) {
-        texture.deleteTexture();
-    }
-}
-
-void GlLayer::onGlContextLost() {
-    texture.deleteTexture();
-}
-
-void GlLayer::setRenderTarget(GLenum renderTarget) {
-    if (renderTarget != getRenderTarget()) {
-        // new render target: bind with new target, and update filter/wrap
-        texture.mTarget = renderTarget;
-        if (texture.mId) {
-            caches.textureState().bindTexture(texture.target(), texture.mId);
-        }
-        texture.setFilter(GL_NEAREST, false, true);
-        texture.setWrap(GL_CLAMP_TO_EDGE, false, true);
-    }
-}
-
-void GlLayer::generateTexture() {
-    if (!texture.mId) {
-        glGenTextures(1, &texture.mId);
-    }
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/GlLayer.h b/libs/hwui/GlLayer.h
deleted file mode 100644
index 9f70fda..0000000
--- a/libs/hwui/GlLayer.h
+++ /dev/null
@@ -1,75 +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.
- */
-
-#pragma once
-
-#include "Layer.h"
-
-#include "Texture.h"
-
-namespace android {
-namespace uirenderer {
-
-// Forward declarations
-class Caches;
-
-/**
- * A layer has dimensions and is backed by an OpenGL texture or FBO.
- */
-class GlLayer : public Layer {
-public:
-    GlLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-            sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend);
-    virtual ~GlLayer();
-
-    uint32_t getWidth() const override { return texture.mWidth; }
-
-    uint32_t getHeight() const override { return texture.mHeight; }
-
-    void setSize(uint32_t width, uint32_t height) override {
-        texture.updateLayout(width, height, texture.internalFormat(), texture.format(),
-                             texture.target());
-    }
-
-    void setBlend(bool blend) override { texture.blend = blend; }
-
-    bool isBlend() const override { return texture.blend; }
-
-    inline GLuint getTextureId() const { return texture.id(); }
-
-    inline GLenum getRenderTarget() const { return texture.target(); }
-
-    void setRenderTarget(GLenum renderTarget);
-
-    void generateTexture();
-
-    /**
-     * Lost the GL context but the layer is still around, mark it invalid internally
-     * so the dtor knows not to do any GL work
-     */
-    void onGlContextLost();
-
-private:
-    Caches& caches;
-
-    /**
-     * The texture backing this layer.
-     */
-    Texture texture;
-};  // struct GlLayer
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp
index 612bfde..a9a7af8 100644
--- a/libs/hwui/GpuMemoryTracker.cpp
+++ b/libs/hwui/GpuMemoryTracker.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include "Texture.h"
 #include "utils/StringUtils.h"
 
 #include <GpuMemoryTracker.h>
@@ -117,22 +116,6 @@
             ATRACE_INT(buf, stats.count);
         }
     }
-
-    std::vector<const Texture*> freeList;
-    for (const auto& obj : gObjectSet) {
-        if (obj->objectType() == GpuObjectType::Texture) {
-            const Texture* texture = static_cast<Texture*>(obj);
-            if (texture->cleanup) {
-                ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u", texture->id(),
-                      texture->width(), texture->height());
-                freeList.push_back(texture);
-            }
-        }
-    }
-    for (auto& texture : freeList) {
-        const_cast<Texture*>(texture)->deleteTexture();
-        delete texture;
-    }
 }
 
 }  // namespace uirenderer
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index fb8f033..f59a2e6 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -17,17 +17,17 @@
 #include "Layer.h"
 
 #include "renderstate/RenderState.h"
+#include "utils/Color.h"
 
 #include <SkToSRGBColorFilter.h>
 
 namespace android {
 namespace uirenderer {
 
-Layer::Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter> colorFilter, int alpha,
-             SkBlendMode mode)
+Layer::Layer(RenderState& renderState, sk_sp<SkColorFilter> colorFilter, int alpha,
+        SkBlendMode mode)
         : GpuMemoryTracker(GpuObjectType::Layer)
         , mRenderState(renderState)
-        , mApi(api)
         , mColorFilter(colorFilter)
         , alpha(alpha)
         , mode(mode) {
@@ -36,6 +36,8 @@
     incStrong(nullptr);
     buildColorSpaceWithFilter();
     renderState.registerLayer(this);
+    texTransform.setIdentity();
+    transform.setIdentity();
 }
 
 Layer::~Layer() {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 31878ac..c4e4c1c 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -23,8 +23,9 @@
 #include <SkColorFilter.h>
 #include <SkColorSpace.h>
 #include <SkPaint.h>
-
-#include "Matrix.h"
+#include <SkImage.h>
+#include <SkMatrix.h>
+#include <system/graphics.h>
 
 namespace android {
 namespace uirenderer {
@@ -40,24 +41,19 @@
  */
 class Layer : public VirtualLightRefBase, GpuMemoryTracker {
 public:
-    enum class Api {
-        OpenGL = 0,
-        Vulkan = 1,
-    };
-
-    Api getApi() const { return mApi; }
+    Layer(RenderState& renderState, sk_sp<SkColorFilter>, int alpha, SkBlendMode mode);
 
     ~Layer();
 
-    virtual uint32_t getWidth() const = 0;
+    virtual uint32_t getWidth() const { return mWidth; }
 
-    virtual uint32_t getHeight() const = 0;
+    virtual uint32_t getHeight() const { return mHeight; }
 
-    virtual void setSize(uint32_t width, uint32_t height) = 0;
+    virtual void setSize(uint32_t width, uint32_t height) { mWidth = width; mHeight = height; }
 
-    virtual void setBlend(bool blend) = 0;
+    virtual void setBlend(bool blend) { mBlend = blend; }
 
-    virtual bool isBlend() const = 0;
+    virtual bool isBlend() const { return mBlend; }
 
     inline void setForceFilter(bool forceFilter) { this->forceFilter = forceFilter; }
 
@@ -84,9 +80,9 @@
 
     inline sk_sp<SkColorFilter> getColorSpaceWithFilter() const { return mColorSpaceWithFilter; }
 
-    inline mat4& getTexTransform() { return texTransform; }
+    inline SkMatrix& getTexTransform() { return texTransform; }
 
-    inline mat4& getTransform() { return transform; }
+    inline SkMatrix& getTransform() { return transform; }
 
     /**
      * Posts a decStrong call to the appropriate thread.
@@ -94,16 +90,17 @@
      */
     void postDecStrong();
 
+    inline void setImage(const sk_sp<SkImage>& image) { this->layerImage = image; }
+
+    inline sk_sp<SkImage> getImage() const { return this->layerImage; }
+
 protected:
-    Layer(RenderState& renderState, Api api, sk_sp<SkColorFilter>, int alpha, SkBlendMode mode);
 
     RenderState& mRenderState;
 
 private:
     void buildColorSpaceWithFilter();
 
-    Api mApi;
-
     /**
      * Color filter used to draw this layer. Optional.
      */
@@ -137,12 +134,32 @@
     /**
      * Optional texture coordinates transform.
      */
-    mat4 texTransform;
+    SkMatrix texTransform;
 
     /**
      * Optional transform.
      */
-    mat4 transform;
+    SkMatrix transform;
+
+    /**
+     * An image backing the layer.
+     */
+    sk_sp<SkImage> layerImage;
+
+    /**
+     * layer width.
+     */
+    uint32_t mWidth = 0;
+
+    /**
+     * layer height.
+     */
+    uint32_t mHeight = 0;
+
+    /**
+     * enable blending
+     */
+    bool mBlend = false;
 
 };  // struct Layer
 
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
deleted file mode 100644
index 910a988..0000000
--- a/libs/hwui/PixelBuffer.cpp
+++ /dev/null
@@ -1,156 +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.
- */
-
-#include "PixelBuffer.h"
-
-#include "Debug.h"
-#include "Extensions.h"
-#include "Properties.h"
-#include "renderstate/RenderState.h"
-#include "utils/GLUtils.h"
-
-#include <utils/Log.h>
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// CPU pixel buffer
-///////////////////////////////////////////////////////////////////////////////
-
-class CpuPixelBuffer : public PixelBuffer {
-public:
-    CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
-
-    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
-
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
-
-protected:
-    void unmap() override;
-
-private:
-    std::unique_ptr<uint8_t[]> mBuffer;
-};
-
-CpuPixelBuffer::CpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
-        : PixelBuffer(format, width, height)
-        , mBuffer(new uint8_t[width * height * formatSize(format)]) {}
-
-uint8_t* CpuPixelBuffer::map(AccessMode mode) {
-    if (mAccessMode == kAccessMode_None) {
-        mAccessMode = mode;
-    }
-    return mBuffer.get();
-}
-
-void CpuPixelBuffer::unmap() {
-    mAccessMode = kAccessMode_None;
-}
-
-void CpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
-    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
-                    &mBuffer[offset]);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// GPU pixel buffer
-///////////////////////////////////////////////////////////////////////////////
-
-class GpuPixelBuffer : public PixelBuffer {
-public:
-    GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height);
-    ~GpuPixelBuffer();
-
-    uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) override;
-
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) override;
-
-protected:
-    void unmap() override;
-
-private:
-    GLuint mBuffer;
-    uint8_t* mMappedPointer;
-    Caches& mCaches;
-};
-
-GpuPixelBuffer::GpuPixelBuffer(GLenum format, uint32_t width, uint32_t height)
-        : PixelBuffer(format, width, height)
-        , mMappedPointer(nullptr)
-        , mCaches(Caches::getInstance()) {
-    glGenBuffers(1, &mBuffer);
-
-    mCaches.pixelBufferState().bind(mBuffer);
-    glBufferData(GL_PIXEL_UNPACK_BUFFER, getSize(), nullptr, GL_DYNAMIC_DRAW);
-    mCaches.pixelBufferState().unbind();
-}
-
-GpuPixelBuffer::~GpuPixelBuffer() {
-    glDeleteBuffers(1, &mBuffer);
-}
-
-uint8_t* GpuPixelBuffer::map(AccessMode mode) {
-    if (mAccessMode == kAccessMode_None) {
-        mCaches.pixelBufferState().bind(mBuffer);
-        mMappedPointer = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, getSize(), mode);
-        if (CC_UNLIKELY(!mMappedPointer)) {
-            GLUtils::dumpGLErrors();
-            LOG_ALWAYS_FATAL("Failed to map PBO");
-        }
-        mAccessMode = mode;
-        mCaches.pixelBufferState().unbind();
-    }
-
-    return mMappedPointer;
-}
-
-void GpuPixelBuffer::unmap() {
-    if (mAccessMode != kAccessMode_None) {
-        if (mMappedPointer) {
-            mCaches.pixelBufferState().bind(mBuffer);
-            GLboolean status = glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-            if (status == GL_FALSE) {
-                ALOGE("Corrupted GPU pixel buffer");
-            }
-        }
-        mAccessMode = kAccessMode_None;
-        mMappedPointer = nullptr;
-    }
-}
-
-void GpuPixelBuffer::upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) {
-    // If the buffer is not mapped, unmap() will not bind it
-    mCaches.pixelBufferState().bind(mBuffer);
-    unmap();
-    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat, GL_UNSIGNED_BYTE,
-                    reinterpret_cast<void*>(offset));
-    mCaches.pixelBufferState().unbind();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Factory
-///////////////////////////////////////////////////////////////////////////////
-
-PixelBuffer* PixelBuffer::create(GLenum format, uint32_t width, uint32_t height, BufferType type) {
-    if (type == kBufferType_Auto && Caches::getInstance().gpuPixelBuffersEnabled) {
-        return new GpuPixelBuffer(format, width, height);
-    }
-    return new CpuPixelBuffer(format, width, height);
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/PixelBuffer.h b/libs/hwui/PixelBuffer.h
deleted file mode 100644
index e7e341b..0000000
--- a/libs/hwui/PixelBuffer.h
+++ /dev/null
@@ -1,198 +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.
- */
-
-#ifndef ANDROID_HWUI_PIXEL_BUFFER_H
-#define ANDROID_HWUI_PIXEL_BUFFER_H
-
-#include <GLES3/gl3.h>
-
-#include <log/log.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Represents a pixel buffer. A pixel buffer will be backed either by a
- * PBO on OpenGL ES 3.0 and higher or by an array of uint8_t on other
- * versions. If the buffer is backed by a PBO it will of type
- * GL_PIXEL_UNPACK_BUFFER.
- *
- * To read from or write into a PixelBuffer you must first map the
- * buffer using the map(AccessMode) method. This method returns a
- * pointer to the beginning of the buffer.
- *
- * Before the buffer can be used by the GPU, for instance to upload
- * a texture, you must first unmap the buffer. To do so, call the
- * unmap() method.
- *
- * Mapping and unmapping a PixelBuffer can have the side effect of
- * changing the currently active GL_PIXEL_UNPACK_BUFFER. It is
- * therefore recommended to call Caches::unbindPixelbuffer() after
- * using a PixelBuffer to upload to a texture.
- */
-class PixelBuffer {
-public:
-    enum BufferType { kBufferType_Auto, kBufferType_CPU };
-
-    enum AccessMode {
-        kAccessMode_None = 0,
-        kAccessMode_Read = GL_MAP_READ_BIT,
-        kAccessMode_Write = GL_MAP_WRITE_BIT,
-        kAccessMode_ReadWrite = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT
-    };
-
-    /**
-     * Creates a new PixelBuffer object with the specified format and
-     * dimensions. The buffer is immediately allocated.
-     *
-     * The buffer type specifies how the buffer should be allocated.
-     * By default this method will automatically choose whether to allocate
-     * a CPU or GPU buffer.
-     */
-    static PixelBuffer* create(GLenum format, uint32_t width, uint32_t height,
-                               BufferType type = kBufferType_Auto);
-
-    virtual ~PixelBuffer() {}
-
-    /**
-     * Returns the format of this render buffer.
-     */
-    GLenum getFormat() const { return mFormat; }
-
-    /**
-     * Maps this before with the specified access mode. This method
-     * returns a pointer to the region of memory where the buffer was
-     * mapped.
-     *
-     * If the buffer is already mapped when this method is invoked,
-     * this method will return the previously mapped pointer. The
-     * access mode can only be changed by calling unmap() first.
-     *
-     * The specified access mode cannot be kAccessMode_None.
-     */
-    virtual uint8_t* map(AccessMode mode = kAccessMode_ReadWrite) = 0;
-
-    /**
-     * Returns the current access mode for this buffer. If the buffer
-     * is not mapped, this method returns kAccessMode_None.
-     */
-    AccessMode getAccessMode() const { return mAccessMode; }
-
-    /**
-     * Upload the specified rectangle of this pixel buffer as a
-     * GL_TEXTURE_2D texture. Calling this method will trigger
-     * an unmap() if necessary.
-     */
-    virtual void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height, int offset) = 0;
-
-    /**
-     * Upload the specified rectangle of this pixel buffer as a
-     * GL_TEXTURE_2D texture. Calling this method will trigger
-     * an unmap() if necessary.
-     *
-     * This is a convenience function provided to save callers the
-     * trouble of computing the offset parameter.
-     */
-    void upload(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
-        upload(x, y, width, height, getOffset(x, y));
-    }
-
-    /**
-     * Returns the width of the render buffer in pixels.
-     */
-    uint32_t getWidth() const { return mWidth; }
-
-    /**
-     * Returns the height of the render buffer in pixels.
-     */
-    uint32_t getHeight() const { return mHeight; }
-
-    /**
-     * Returns the size of this pixel buffer in bytes.
-     */
-    uint32_t getSize() const { return mWidth * mHeight * formatSize(mFormat); }
-
-    /**
-     * Returns the offset of a pixel in this pixel buffer, in bytes.
-     */
-    uint32_t getOffset(uint32_t x, uint32_t y) const {
-        return (y * mWidth + x) * formatSize(mFormat);
-    }
-
-    /**
-     * Returns the number of bytes per pixel in the specified format.
-     *
-     * Supported formats:
-     *      GL_ALPHA
-     *      GL_RGBA
-     */
-    static uint32_t formatSize(GLenum format) {
-        switch (format) {
-            case GL_ALPHA:
-                return 1;
-            case GL_RGBA:
-                return 4;
-        }
-        return 0;
-    }
-
-    /**
-     * Returns the alpha channel offset in the specified format.
-     *
-     * Supported formats:
-     *      GL_ALPHA
-     *      GL_RGBA
-     */
-    static uint32_t formatAlphaOffset(GLenum format) {
-        switch (format) {
-            case GL_ALPHA:
-                return 0;
-            case GL_RGBA:
-                return 3;
-        }
-
-        ALOGE("unsupported format: %d", format);
-        return 0;
-    }
-
-protected:
-    /**
-     * Creates a new render buffer in the specified format and dimensions.
-     * The format must be GL_ALPHA or GL_RGBA.
-     */
-    PixelBuffer(GLenum format, uint32_t width, uint32_t height)
-            : mFormat(format), mWidth(width), mHeight(height), mAccessMode(kAccessMode_None) {}
-
-    /**
-     * Unmaps this buffer, if needed. After the buffer is unmapped,
-     * the pointer previously returned by map() becomes invalid and
-     * should not be used.
-     */
-    virtual void unmap() = 0;
-
-    GLenum mFormat;
-
-    uint32_t mWidth;
-    uint32_t mHeight;
-
-    AccessMode mAccessMode;
-
-};  // class PixelBuffer
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_PIXEL_BUFFER_H
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0766e3b..7966845 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include "Caches.h"
 #include "DeviceInfo.h"
 #include "Outline.h"
 #include "Rect.h"
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 464a58d..65bee47 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "ResourceCache.h"
-#include "Caches.h"
 
 namespace android {
 
@@ -112,13 +111,9 @@
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
     if (ref == nullptr) {
         // If we're not tracking this resource, just delete it
-        if (Caches::hasInstance()) {
-            // DEAD CODE
-        } else {
-            // A Res_png_9patch is actually an array of byte that's larger
-            // than sizeof(Res_png_9patch). It must be freed as an array.
-            delete[](int8_t*) resource;
-        }
+        // A Res_png_9patch is actually an array of byte that's larger
+        // than sizeof(Res_png_9patch). It must be freed as an array.
+        delete[](int8_t*) resource;
         return;
     }
     ref->destroyed = true;
@@ -135,14 +130,10 @@
     if (ref->destroyed) {
         switch (ref->resourceType) {
             case kNinePatch: {
-                if (Caches::hasInstance()) {
-                    // DEAD CODE
-                } else {
-                    // A Res_png_9patch is actually an array of byte that's larger
-                    // than sizeof(Res_png_9patch). It must be freed as an array.
-                    int8_t* patch = (int8_t*)resource;
-                    delete[] patch;
-                }
+                // A Res_png_9patch is actually an array of byte that's larger
+                // than sizeof(Res_png_9patch). It must be freed as an array.
+                int8_t* patch = (int8_t*)resource;
+                delete[] patch;
             } break;
         }
     }
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
deleted file mode 100644
index 1e90eeb..0000000
--- a/libs/hwui/Texture.cpp
+++ /dev/null
@@ -1,413 +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.
- */
-
-#include "Texture.h"
-#include "Caches.h"
-#include "utils/GLUtils.h"
-#include "utils/MathUtils.h"
-#include "utils/TraceUtils.h"
-
-#include <utils/Log.h>
-
-#include <math/mat4.h>
-
-#include <SkCanvas.h>
-
-namespace android {
-namespace uirenderer {
-
-// Number of bytes used by a texture in the given format
-static int bytesPerPixel(GLint glFormat) {
-    switch (glFormat) {
-        // The wrapped-texture case, usually means a SurfaceTexture
-        case 0:
-            return 0;
-        case GL_LUMINANCE:
-        case GL_ALPHA:
-            return 1;
-        case GL_SRGB8:
-        case GL_RGB:
-            return 3;
-        case GL_SRGB8_ALPHA8:
-        case GL_RGBA:
-            return 4;
-        case GL_RGBA16F:
-            return 8;
-        default:
-            LOG_ALWAYS_FATAL("UNKNOWN FORMAT 0x%x", glFormat);
-    }
-}
-
-void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force) {
-    if (force || wrapS != mWrapS || wrapT != mWrapT) {
-        mWrapS = wrapS;
-        mWrapT = wrapT;
-
-        if (bindTexture) {
-            mCaches.textureState().bindTexture(mTarget, mId);
-        }
-
-        glTexParameteri(mTarget, GL_TEXTURE_WRAP_S, wrapS);
-        glTexParameteri(mTarget, GL_TEXTURE_WRAP_T, wrapT);
-    }
-}
-
-void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool force) {
-    if (force || min != mMinFilter || mag != mMagFilter) {
-        mMinFilter = min;
-        mMagFilter = mag;
-
-        if (bindTexture) {
-            mCaches.textureState().bindTexture(mTarget, mId);
-        }
-
-        if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR;
-
-        glTexParameteri(mTarget, GL_TEXTURE_MIN_FILTER, min);
-        glTexParameteri(mTarget, GL_TEXTURE_MAG_FILTER, mag);
-    }
-}
-
-void Texture::deleteTexture() {
-    mCaches.textureState().deleteTexture(mId);
-    mId = 0;
-    mTarget = GL_NONE;
-    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
-        EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
-        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
-        mEglImageHandle = EGL_NO_IMAGE_KHR;
-    }
-}
-
-bool Texture::updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                           GLenum target) {
-    if (mWidth == width && mHeight == height && mFormat == format &&
-        mInternalFormat == internalFormat && mTarget == target) {
-        return false;
-    }
-    mWidth = width;
-    mHeight = height;
-    mFormat = format;
-    mInternalFormat = internalFormat;
-    mTarget = target;
-    notifySizeChanged(mWidth * mHeight * bytesPerPixel(internalFormat));
-    return true;
-}
-
-void Texture::resetCachedParams() {
-    mWrapS = GL_REPEAT;
-    mWrapT = GL_REPEAT;
-    mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
-    mMagFilter = GL_LINEAR;
-}
-
-void Texture::upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format,
-                     GLenum type, const void* pixels) {
-    GL_CHECKPOINT(MODERATE);
-
-    // We don't have color space information, we assume the data is gamma encoded
-    mIsLinear = false;
-
-    bool needsAlloc = updateLayout(width, height, internalFormat, format, GL_TEXTURE_2D);
-    if (!mId) {
-        glGenTextures(1, &mId);
-        needsAlloc = true;
-        resetCachedParams();
-    }
-    mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId);
-    if (needsAlloc) {
-        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
-    } else if (pixels) {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, pixels);
-    }
-    GL_CHECKPOINT(MODERATE);
-}
-
-void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
-    EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
-    if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
-        eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
-        mEglImageHandle = EGL_NO_IMAGE_KHR;
-    }
-    mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                        buffer->getNativeBuffer(), 0);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
-}
-
-static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
-                            GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height,
-                            const GLvoid* data) {
-    const bool useStride =
-            stride != width && Caches::getInstance().extensions().hasUnpackRowLength();
-    if ((stride == width) || useStride) {
-        if (useStride) {
-            glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
-        }
-
-        if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, data);
-        } else {
-            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data);
-        }
-
-        if (useStride) {
-            glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-        }
-    } else {
-        //  With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer
-        //  if the stride doesn't match the width
-
-        GLvoid* temp = (GLvoid*)malloc(width * height * bpp);
-        if (!temp) return;
-
-        uint8_t* pDst = (uint8_t*)temp;
-        uint8_t* pSrc = (uint8_t*)data;
-        for (GLsizei i = 0; i < height; i++) {
-            memcpy(pDst, pSrc, width * bpp);
-            pDst += width * bpp;
-            pSrc += stride * bpp;
-        }
-
-        if (resize) {
-            glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, temp);
-        } else {
-            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp);
-        }
-
-        free(temp);
-    }
-}
-
-void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType, bool needSRGB,
-                                         GLint* outInternalFormat, GLint* outFormat,
-                                         GLint* outType) {
-    switch (colorType) {
-        case kAlpha_8_SkColorType:
-            *outFormat = GL_ALPHA;
-            *outInternalFormat = GL_ALPHA;
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kRGB_565_SkColorType:
-            if (needSRGB) {
-                // We would ideally use a GL_RGB/GL_SRGB8 texture but the
-                // intermediate Skia bitmap needs to be ARGB_8888
-                *outFormat = GL_RGBA;
-                *outInternalFormat = caches.rgbaInternalFormat();
-                *outType = GL_UNSIGNED_BYTE;
-            } else {
-                *outFormat = GL_RGB;
-                *outInternalFormat = GL_RGB;
-                *outType = GL_UNSIGNED_SHORT_5_6_5;
-            }
-            break;
-        // ARGB_4444 is upconverted to RGBA_8888
-        case kARGB_4444_SkColorType:
-        case kN32_SkColorType:
-            *outFormat = GL_RGBA;
-            *outInternalFormat = caches.rgbaInternalFormat(needSRGB);
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kGray_8_SkColorType:
-            *outFormat = GL_LUMINANCE;
-            *outInternalFormat = GL_LUMINANCE;
-            *outType = GL_UNSIGNED_BYTE;
-            break;
-        case kRGBA_F16_SkColorType:
-            if (caches.extensions().getMajorGlVersion() >= 3) {
-                // This format is always linear
-                *outFormat = GL_RGBA;
-                *outInternalFormat = GL_RGBA16F;
-                *outType = GL_HALF_FLOAT;
-            } else {
-                *outFormat = GL_RGBA;
-                *outInternalFormat = caches.rgbaInternalFormat(true);
-                *outType = GL_UNSIGNED_BYTE;
-            }
-            break;
-        default:
-            LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
-            break;
-    }
-}
-
-SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
-                              sk_sp<SkColorSpace> sRGB) {
-    SkBitmap rgbaBitmap;
-    rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
-                                                bitmap.info().alphaType(),
-                                                hasLinearBlending ? sRGB : nullptr));
-    rgbaBitmap.eraseColor(0);
-
-    if (bitmap.colorType() == kRGBA_F16_SkColorType) {
-        // Drawing RGBA_F16 onto ARGB_8888 is not supported
-        bitmap.readPixels(rgbaBitmap.info().makeColorSpace(SkColorSpace::MakeSRGB()),
-                          rgbaBitmap.getPixels(), rgbaBitmap.rowBytes(), 0, 0);
-    } else {
-        SkCanvas canvas(rgbaBitmap);
-        canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
-    }
-
-    return rgbaBitmap;
-}
-
-bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending) {
-    return info.colorType() == kARGB_4444_SkColorType ||
-           (info.colorType() == kRGB_565_SkColorType && hasLinearBlending &&
-            info.colorSpace()->isSRGB()) ||
-           (info.colorType() == kRGBA_F16_SkColorType &&
-            Caches::getInstance().extensions().getMajorGlVersion() < 3);
-}
-
-void Texture::upload(Bitmap& bitmap) {
-    ATRACE_FORMAT("Upload %ux%u Texture", bitmap.width(), bitmap.height());
-
-    // We could also enable mipmapping if both bitmap dimensions are powers
-    // of 2 but we'd have to deal with size changes. Let's keep this simple
-    const bool canMipMap = mCaches.extensions().hasNPot();
-
-    // If the texture had mipmap enabled but not anymore,
-    // force a glTexImage2D to discard the mipmap levels
-    bool needsAlloc = canMipMap && mipMap && !bitmap.hasHardwareMipMap();
-    bool setDefaultParams = false;
-
-    if (!mId) {
-        glGenTextures(1, &mId);
-        needsAlloc = true;
-        setDefaultParams = true;
-    }
-
-    bool hasLinearBlending = mCaches.extensions().hasLinearBlending();
-    bool needSRGB = transferFunctionCloseToSRGB(bitmap.info().colorSpace());
-
-    GLint internalFormat, format, type;
-    colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB && hasLinearBlending,
-                               &internalFormat, &format, &type);
-
-    // Some devices don't support GL_RGBA16F, so we need to compare the color type
-    // and internal GL format to decide what to do with 16 bit bitmaps
-    bool rgba16fNeedsConversion =
-            bitmap.colorType() == kRGBA_F16_SkColorType && internalFormat != GL_RGBA16F;
-
-    // RGBA16F is always linear extended sRGB
-    if (internalFormat == GL_RGBA16F) {
-        mIsLinear = true;
-    }
-
-    mConnector.reset();
-
-    // Alpha masks don't have color profiles
-    // If an RGBA16F bitmap needs conversion, we know the target will be sRGB
-    if (!mIsLinear && internalFormat != GL_ALPHA && !rgba16fNeedsConversion) {
-        SkColorSpace* colorSpace = bitmap.info().colorSpace();
-        // If the bitmap is sRGB we don't need conversion
-        if (colorSpace != nullptr && !colorSpace->isSRGB()) {
-            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
-            if (!colorSpace->toXYZD50(&xyzMatrix)) {
-                ALOGW("Incompatible color space!");
-            } else {
-                SkColorSpaceTransferFn fn;
-                if (!colorSpace->isNumericalTransferFn(&fn)) {
-                    ALOGW("Incompatible color space, no numerical transfer function!");
-                } else {
-                    float data[16];
-                    xyzMatrix.asColMajorf(data);
-
-                    ColorSpace::TransferParameters p = {fn.fG, fn.fA, fn.fB, fn.fC,
-                                                        fn.fD, fn.fE, fn.fF};
-                    ColorSpace src("Unnamed", mat4f((const float*)&data[0]).upperLeft(), p);
-                    mConnector.reset(new ColorSpaceConnector(src, ColorSpace::sRGB()));
-
-                    // A non-sRGB color space might have a transfer function close enough to sRGB
-                    // that we can save shader instructions by using an sRGB sampler
-                    // This is only possible if we have hardware support for sRGB textures
-                    if (needSRGB && internalFormat == GL_RGBA && mCaches.extensions().hasSRGB() &&
-                        !bitmap.isHardware()) {
-                        internalFormat = GL_SRGB8_ALPHA8;
-                    }
-                }
-            }
-        }
-    }
-
-    GLenum target = bitmap.isHardware() ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
-    needsAlloc |= updateLayout(bitmap.width(), bitmap.height(), internalFormat, format, target);
-
-    blend = !bitmap.isOpaque();
-    mCaches.textureState().bindTexture(mTarget, mId);
-
-    // TODO: Handle sRGB gray bitmaps
-    if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasLinearBlending))) {
-        SkBitmap skBitmap;
-        bitmap.getSkBitmap(&skBitmap);
-        sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeSRGB();
-        SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasLinearBlending, std::move(sRGB));
-        uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
-                        rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(), rgbaBitmap.height(),
-                        rgbaBitmap.getPixels());
-    } else if (bitmap.isHardware()) {
-        uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
-    } else {
-        uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
-                        bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(),
-                        bitmap.pixels());
-    }
-
-    if (canMipMap) {
-        mipMap = bitmap.hasHardwareMipMap();
-        if (mipMap) {
-            glGenerateMipmap(GL_TEXTURE_2D);
-        }
-    }
-
-    if (setDefaultParams) {
-        setFilter(GL_NEAREST);
-        setWrap(GL_CLAMP_TO_EDGE);
-    }
-}
-
-void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                   GLenum target) {
-    mId = id;
-    mWidth = width;
-    mHeight = height;
-    mFormat = format;
-    mInternalFormat = internalFormat;
-    mTarget = target;
-    mConnector.reset();
-    // We're wrapping an existing texture, so don't double count this memory
-    notifySizeChanged(0);
-}
-
-TransferFunctionType Texture::getTransferFunctionType() const {
-    if (mConnector.get() != nullptr && mInternalFormat != GL_SRGB8_ALPHA8) {
-        const ColorSpace::TransferParameters& p = mConnector->getSource().getTransferParameters();
-        if (MathUtils::isZero(p.e) && MathUtils::isZero(p.f)) {
-            if (MathUtils::areEqual(p.a, 1.0f) && MathUtils::isZero(p.b) &&
-                MathUtils::isZero(p.c) && MathUtils::isZero(p.d)) {
-                if (MathUtils::areEqual(p.g, 1.0f)) {
-                    return TransferFunctionType::None;
-                }
-                return TransferFunctionType::Gamma;
-            }
-            return TransferFunctionType::Limited;
-        }
-        return TransferFunctionType::Full;
-    }
-    return TransferFunctionType::None;
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
deleted file mode 100644
index 5b7e4e2..0000000
--- a/libs/hwui/Texture.h
+++ /dev/null
@@ -1,228 +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.
- */
-
-#ifndef ANDROID_HWUI_TEXTURE_H
-#define ANDROID_HWUI_TEXTURE_H
-
-#include "GpuMemoryTracker.h"
-#include "hwui/Bitmap.h"
-#include "utils/Color.h"
-
-#include <memory>
-
-#include <math/mat3.h>
-
-#include <ui/ColorSpace.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES3/gl3.h>
-#include <SkBitmap.h>
-
-namespace android {
-
-class GraphicBuffer;
-
-namespace uirenderer {
-
-class Caches;
-class UvMapper;
-class Layer;
-
-/**
- * Represents an OpenGL texture.
- */
-class Texture : public GpuMemoryTracker {
-public:
-    static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasLinearBlending,
-                                sk_sp<SkColorSpace> sRGB);
-    static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasLinearBlending);
-    static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
-                                           bool needSRGB, GLint* outInternalFormat,
-                                           GLint* outFormat, GLint* outType);
-
-    explicit Texture(Caches& caches) : GpuMemoryTracker(GpuObjectType::Texture), mCaches(caches) {}
-
-    virtual ~Texture() {}
-
-    inline void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
-        setWrapST(wrap, wrap, bindTexture, force);
-    }
-
-    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
-                           bool force = false);
-
-    inline void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
-        setFilterMinMag(filter, filter, bindTexture, force);
-    }
-
-    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
-                                 bool force = false);
-
-    /**
-     * Convenience method to call glDeleteTextures() on this texture's id.
-     */
-    void deleteTexture();
-
-    /**
-     * Sets the width, height, and format of the texture along with allocating
-     * the texture ID. Does nothing if the width, height, and format are already
-     * the requested values.
-     *
-     * The image data is undefined after calling this.
-     */
-    void resize(uint32_t width, uint32_t height, GLint internalFormat, GLint format) {
-        upload(internalFormat, width, height, format,
-               internalFormat == GL_RGBA16F ? GL_HALF_FLOAT : GL_UNSIGNED_BYTE, nullptr);
-    }
-
-    /**
-     * Updates this Texture with the contents of the provided Bitmap,
-     * also setting the appropriate width, height, and format. It is not necessary
-     * to call resize() prior to this.
-     *
-     * Note this does not set the generation from the Bitmap.
-     */
-    void upload(Bitmap& source);
-
-    /**
-     * Basically glTexImage2D/glTexSubImage2D.
-     */
-    void upload(GLint internalFormat, uint32_t width, uint32_t height, GLenum format, GLenum type,
-                const void* pixels);
-
-    /**
-     * Wraps an existing texture.
-     */
-    void wrap(GLuint id, uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-              GLenum target);
-
-    GLuint id() const { return mId; }
-
-    uint32_t width() const { return mWidth; }
-
-    uint32_t height() const { return mHeight; }
-
-    GLint format() const { return mFormat; }
-
-    GLint internalFormat() const { return mInternalFormat; }
-
-    GLenum target() const { return mTarget; }
-
-    /**
-     * Returns nullptr if this texture does not require color space conversion
-     * to sRGB, or a valid pointer to a ColorSpaceConnector if a conversion
-     * is required.
-     */
-    constexpr const ColorSpaceConnector* getColorSpaceConnector() const { return mConnector.get(); }
-
-    constexpr bool hasColorSpaceConversion() const { return mConnector.get() != nullptr; }
-
-    TransferFunctionType getTransferFunctionType() const;
-
-    /**
-     * Returns true if this texture uses a linear encoding format.
-     */
-    constexpr bool isLinear() const { return mIsLinear; }
-
-    /**
-     * Generation of the backing bitmap,
-     */
-    uint32_t generation = 0;
-    /**
-     * Indicates whether the texture requires blending.
-     */
-    bool blend = false;
-    /**
-     * Indicates whether this texture should be cleaned up after use.
-     */
-    bool cleanup = false;
-    /**
-     * Optional, size of the original bitmap.
-     */
-    uint32_t bitmapSize = 0;
-    /**
-     * Indicates whether this texture will use trilinear filtering.
-     */
-    bool mipMap = false;
-
-    /**
-     * Optional, pointer to a texture coordinates mapper.
-     */
-    const UvMapper* uvMapper = nullptr;
-
-    /**
-     * Whether or not the Texture is marked in use and thus not evictable for
-     * the current frame. This is reset at the start of a new frame.
-     */
-    void* isInUse = nullptr;
-
-private:
-    // TODO: Temporarily grant private access to GlLayer, remove once
-    // GlLayer can be de-tangled from being a dual-purpose render target
-    // and external texture wrapper
-    friend class GlLayer;
-
-    // Returns true if the texture layout (size, format, etc.) changed, false if it was the same
-    bool updateLayout(uint32_t width, uint32_t height, GLint internalFormat, GLint format,
-                      GLenum target);
-    void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
-    void resetCachedParams();
-
-    GLuint mId = 0;
-    uint32_t mWidth = 0;
-    uint32_t mHeight = 0;
-    GLint mFormat = 0;
-    GLint mInternalFormat = 0;
-    GLenum mTarget = GL_NONE;
-    EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;
-
-    /* See GLES spec section 3.8.14
-     * "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
-     * NEAREST_MIPMAP_LINEAR and the value for TEXTURE_MAG_FILTER is LINEAR.
-     * s, t, and r wrap modes are all set to REPEAT."
-     */
-    GLenum mWrapS = GL_REPEAT;
-    GLenum mWrapT = GL_REPEAT;
-    GLenum mMinFilter = GL_NEAREST_MIPMAP_LINEAR;
-    GLenum mMagFilter = GL_LINEAR;
-
-    // Indicates whether the content of the texture is in linear space
-    bool mIsLinear = false;
-
-    Caches& mCaches;
-
-    std::unique_ptr<ColorSpaceConnector> mConnector;
-};  // struct Texture
-
-class AutoTexture {
-public:
-    explicit AutoTexture(Texture* texture) : texture(texture) {}
-    ~AutoTexture() {
-        if (texture && texture->cleanup) {
-            texture->deleteTexture();
-            delete texture;
-        }
-    }
-
-    Texture* const texture;
-};  // class AutoTexture
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_TEXTURE_H
diff --git a/libs/hwui/VkLayer.cpp b/libs/hwui/VkLayer.cpp
deleted file mode 100644
index 30fba7a..0000000
--- a/libs/hwui/VkLayer.cpp
+++ /dev/null
@@ -1,40 +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.
- */
-
-#include "VkLayer.h"
-
-#include "renderstate/RenderState.h"
-
-#include <SkCanvas.h>
-#include <SkSurface.h>
-
-namespace android {
-namespace uirenderer {
-
-void VkLayer::updateTexture() {
-    sk_sp<SkSurface> surface;
-    SkImageInfo info = SkImageInfo::MakeS32(mWidth, mHeight, kPremul_SkAlphaType);
-    surface = SkSurface::MakeRenderTarget(mRenderState.getGrContext(), SkBudgeted::kNo, info);
-    surface->getCanvas()->clear(SK_ColorBLUE);
-    mImage = surface->makeImageSnapshot();
-}
-
-void VkLayer::onVkContextDestroyed() {
-    mImage = nullptr;
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/VkLayer.h b/libs/hwui/VkLayer.h
deleted file mode 100644
index e9664d0..0000000
--- a/libs/hwui/VkLayer.h
+++ /dev/null
@@ -1,70 +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.
- */
-
-#pragma once
-
-#include "Layer.h"
-
-#include <SkImage.h>
-
-namespace android {
-namespace uirenderer {
-/**
- * A layer has dimensions and is backed by a VkImage.
- */
-class VkLayer : public Layer {
-public:
-    VkLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-            sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode, bool blend)
-            : Layer(renderState, Api::Vulkan, colorFilter, alpha, mode)
-            , mWidth(layerWidth)
-            , mHeight(layerHeight)
-            , mBlend(blend) {}
-
-    virtual ~VkLayer() {}
-
-    uint32_t getWidth() const override { return mWidth; }
-
-    uint32_t getHeight() const override { return mHeight; }
-
-    void setSize(uint32_t width, uint32_t height) override {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    void setBlend(bool blend) override { mBlend = blend; }
-
-    bool isBlend() const override { return mBlend; }
-
-    sk_sp<SkImage> getImage() { return mImage; }
-
-    void updateTexture();
-
-    // If we've destroyed the vulkan context (VkInstance, VkDevice, etc.), we must make sure to
-    // destroy any VkImages that were made with that context.
-    void onVkContextDestroyed();
-
-private:
-    int mWidth;
-    int mHeight;
-    bool mBlend;
-
-    sk_sp<SkImage> mImage;
-
-};  // struct VkLayer
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 7a8d026..e7d12de 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -15,11 +15,11 @@
  */
 #include "Bitmap.h"
 
-#include "Caches.h"
 #include "HardwareBitmapUploader.h"
 #include "Properties.h"
 #include "renderthread/RenderProxy.h"
 #include "utils/Color.h"
+#include <utils/Trace.h>
 
 #include <sys/mman.h>
 
diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
index 1f83d1a..dcfe6b3 100644
--- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h
+++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
@@ -94,11 +94,6 @@
         mOutput << mIdent << "drawPosTextH" << std::endl;
     }
 
-    void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,
-                          const SkPaint&) override {
-        mOutput << mIdent << "drawTextOnPath" << std::endl;
-    }
-
     void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
                            const SkPaint&) override {
         mOutput << mIdent << "drawTextRSXform" << std::endl;
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index c41f6a6..fb66b50 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -15,8 +15,6 @@
  */
 
 #include "LayerDrawable.h"
-#include "GlLayer.h"
-#include "VkLayer.h"
 
 #include "GrBackendSurface.h"
 #include "SkColorFilter.h"
@@ -41,35 +39,14 @@
         return false;
     }
     // transform the matrix based on the layer
-    SkMatrix layerTransform;
-    layer->getTransform().copyTo(layerTransform);
-    sk_sp<SkImage> layerImage;
+    SkMatrix layerTransform = layer->getTransform();
+    sk_sp<SkImage> layerImage = layer->getImage();
     const int layerWidth = layer->getWidth();
     const int layerHeight = layer->getHeight();
-    if (layer->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layer);
-        GrGLTextureInfo externalTexture;
-        externalTexture.fTarget = glLayer->getRenderTarget();
-        externalTexture.fID = glLayer->getTextureId();
-        // The format may not be GL_RGBA8, but given the DeferredLayerUpdater and GLConsumer don't
-        // expose that info we use it as our default.  Further, given that we only use this texture
-        // as a source this will not impact how Skia uses the texture.  The only potential affect
-        // this is anticipated to have is that for some format types if we are not bound as an OES
-        // texture we may get invalid results for SKP capture if we read back the texture.
-        externalTexture.fFormat = GL_RGBA8;
-        GrBackendTexture backendTexture(layerWidth, layerHeight, GrMipMapped::kNo, externalTexture);
-        layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
-                                              kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
-    } else {
-        SkASSERT(layer->getApi() == Layer::Api::Vulkan);
-        VkLayer* vkLayer = static_cast<VkLayer*>(layer);
-        canvas->clear(SK_ColorGREEN);
-        layerImage = vkLayer->getImage();
-    }
 
     if (layerImage) {
         SkMatrix textureMatrixInv;
-        layer->getTexTransform().copyTo(textureMatrixInv);
+        textureMatrixInv = layer->getTexTransform();
         // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
         // use bottom left origin and remove flipV and invert transformations.
         SkMatrix flipV;
@@ -95,6 +72,9 @@
         paint.setAlpha(layer->getAlpha());
         paint.setBlendMode(layer->getMode());
         paint.setColorFilter(layer->getColorSpaceWithFilter());
+        if (layer->getForceFilter()) {
+            paint.setFilterQuality(kLow_SkFilterQuality);
+        }
 
         const bool nonIdentityMatrix = !matrix.isIdentity();
         if (nonIdentityMatrix) {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 78f5a71..2ae3723 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -17,7 +17,6 @@
 #include "SkiaOpenGLPipeline.h"
 
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
 #include "LayerDrawable.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
@@ -187,18 +186,9 @@
     return false;
 }
 
-static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                          sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
-                          bool blend) {
-    GlLayer* layer =
-            new GlLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
-    layer->generateTexture();
-    return layer;
-}
-
 DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
     mRenderThread.requireGlContext();
-    return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::OpenGL);
+    return new DeferredLayerUpdater(mRenderThread.renderState());
 }
 
 void SkiaOpenGLPipeline::onStop() {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index b2519fe..5f2eee4 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -20,7 +20,6 @@
 #include "Readback.h"
 #include "SkiaPipeline.h"
 #include "SkiaProfileRenderer.h"
-#include "VkLayer.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
 
@@ -114,16 +113,10 @@
     return false;
 }
 
-static Layer* createLayer(RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight,
-                          sk_sp<SkColorFilter> colorFilter, int alpha, SkBlendMode mode,
-                          bool blend) {
-    return new VkLayer(renderState, layerWidth, layerHeight, colorFilter, alpha, mode, blend);
-}
-
 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
     mVkManager.initialize();
 
-    return new DeferredLayerUpdater(mRenderThread.renderState(), createLayer, Layer::Api::Vulkan);
+    return new DeferredLayerUpdater(mRenderThread.renderState());
 }
 
 void SkiaVulkanPipeline::onStop() {}
diff --git a/libs/hwui/renderstate/PixelBufferState.cpp b/libs/hwui/renderstate/PixelBufferState.cpp
deleted file mode 100644
index 3a6efb8..0000000
--- a/libs/hwui/renderstate/PixelBufferState.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2015 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 "renderstate/PixelBufferState.h"
-
-namespace android {
-namespace uirenderer {
-
-PixelBufferState::PixelBufferState() : mCurrentPixelBuffer(0) {}
-
-bool PixelBufferState::bind(GLuint buffer) {
-    if (mCurrentPixelBuffer != buffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
-        mCurrentPixelBuffer = buffer;
-        return true;
-    }
-    return false;
-}
-
-bool PixelBufferState::unbind() {
-    if (mCurrentPixelBuffer) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-        mCurrentPixelBuffer = 0;
-        return true;
-    }
-    return false;
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderstate/PixelBufferState.h b/libs/hwui/renderstate/PixelBufferState.h
deleted file mode 100644
index f7ae6c5..0000000
--- a/libs/hwui/renderstate/PixelBufferState.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef RENDERSTATE_PIXELBUFFERSTATE_H
-#define RENDERSTATE_PIXELBUFFERSTATE_H
-
-#include <GLES3/gl3.h>
-
-namespace android {
-namespace uirenderer {
-
-class PixelBufferState {
-    friend class Caches;  // TODO: move to RenderState
-public:
-    bool bind(GLuint buffer);
-    bool unbind();
-
-private:
-    PixelBufferState();
-    GLuint mCurrentPixelBuffer;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif  // RENDERSTATE_PIXELBUFFERSTATE_H
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index 3be84f58..b524bcb 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -16,8 +16,6 @@
 #include "renderstate/RenderState.h"
 #include <GpuMemoryTracker.h>
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
-#include "VkLayer.h"
 #include "Snapshot.h"
 
 #include "renderthread/CanvasContext.h"
@@ -39,44 +37,11 @@
 RenderState::~RenderState() {
 }
 
-void RenderState::onGLContextCreated() {
-    GpuMemoryTracker::onGpuContextCreated();
-
-    // This is delayed because the first access of Caches makes GL calls
-    if (!mCaches) {
-        mCaches = &Caches::createInstance(*this);
-    }
-    mCaches->init();
-}
-
-static void layerLostGlContext(Layer* layer) {
-    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::OpenGL,
-                        "layerLostGlContext on non GL layer");
-    static_cast<GlLayer*>(layer)->onGlContextLost();
-}
-
-void RenderState::onGLContextDestroyed() {
-    // TODO: reset all cached state in state objects
-    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
-
-    mCaches->terminate();
-
-    destroyLayersInUpdater();
-    GpuMemoryTracker::onGpuContextDestroyed();
-}
-
-void RenderState::onVkContextCreated() {
+void RenderState::onContextCreated() {
     GpuMemoryTracker::onGpuContextCreated();
 }
 
-static void layerDestroyedVkContext(Layer* layer) {
-    LOG_ALWAYS_FATAL_IF(layer->getApi() != Layer::Api::Vulkan,
-                        "layerLostVkContext on non Vulkan layer");
-    static_cast<VkLayer*>(layer)->onVkContextDestroyed();
-}
-
-void RenderState::onVkContextDestroyed() {
-    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerDestroyedVkContext);
+void RenderState::onContextDestroyed() {
     destroyLayersInUpdater();
     GpuMemoryTracker::onGpuContextDestroyed();
 }
@@ -85,10 +50,6 @@
     return mRenderThread.getGrContext();
 }
 
-void RenderState::flush(Caches::FlushMode mode) {
-    if (mCaches) mCaches->flush(mode);
-}
-
 void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
     // DEAD CODE
 }
@@ -126,42 +87,6 @@
     glDeleteFramebuffers(1, &fbo);
 }
 
-void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
-    if (mode == DrawGlInfo::kModeProcessNoContext) {
-        // If there's no context we don't need to interrupt as there's
-        // no gl state to save/restore
-        (*functor)(mode, info);
-    } else {
-        interruptForFunctorInvoke();
-        (*functor)(mode, info);
-        resumeFromFunctorInvoke();
-    }
-}
-
-void RenderState::interruptForFunctorInvoke() {
-    mCaches->textureState().resetActiveTexture();
-    debugOverdraw(false, false);
-    // TODO: We need a way to know whether the functor is sRGB aware (b/32072673)
-    if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
-        glDisable(GL_FRAMEBUFFER_SRGB_EXT);
-    }
-}
-
-void RenderState::resumeFromFunctorInvoke() {
-    if (mCaches->extensions().hasLinearBlending() && mCaches->extensions().hasSRGBWriteControl()) {
-        glEnable(GL_FRAMEBUFFER_SRGB_EXT);
-    }
-
-    glViewport(0, 0, mViewportWidth, mViewportHeight);
-    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
-    debugOverdraw(false, false);
-
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    mCaches->textureState().activateTexture(0);
-    mCaches->textureState().resetBoundTextures();
-}
-
 void RenderState::debugOverdraw(bool enable, bool clear) {
     // DEAD CODE
 }
@@ -190,5 +115,9 @@
     // DEAD CODE
 }
 
+renderthread::RenderThread& RenderState::getRenderThread() {
+    return mRenderThread;
+}
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 97785a4..f39aa4b 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -16,8 +16,6 @@
 #ifndef RENDERSTATE_H
 #define RENDERSTATE_H
 
-#include "Caches.h"
-#include "renderstate/PixelBufferState.h"
 #include "utils/Macros.h"
 
 #include <GLES2/gl2.h>
@@ -34,7 +32,6 @@
 namespace android {
 namespace uirenderer {
 
-class Caches;
 class Layer;
 class DeferredLayerUpdater;
 
@@ -44,22 +41,16 @@
 class RenderThread;
 }
 
-// TODO: Replace Cache's GL state tracking with this. For now it's more a thin
 // wrapper of Caches for users to migrate to.
 class RenderState {
     PREVENT_COPY_AND_ASSIGN(RenderState);
     friend class renderthread::RenderThread;
-    friend class Caches;
     friend class renderthread::CacheManager;
 
 public:
-    void onGLContextCreated();
-    void onGLContextDestroyed();
+    void onContextCreated();
+    void onContextDestroyed();
 
-    void onVkContextCreated();
-    void onVkContextDestroyed();
-
-    void flush(Caches::FlushMode flushMode);
     void onBitmapDestroyed(uint32_t pixelRefId);
 
     void setViewport(GLsizei width, GLsizei height);
@@ -70,8 +61,6 @@
     GLuint createFramebuffer();
     void deleteFramebuffer(GLuint fbo);
 
-    void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info);
-
     void debugOverdraw(bool enable, bool clear);
 
     void registerLayer(Layer* layer) { mActiveLayers.insert(layer); }
@@ -101,16 +90,15 @@
 
     void dump();
 
+    renderthread::RenderThread& getRenderThread();
+
 private:
-    void interruptForFunctorInvoke();
-    void resumeFromFunctorInvoke();
     void destroyLayersInUpdater();
 
     explicit RenderState(renderthread::RenderThread& thread);
     ~RenderState();
 
     renderthread::RenderThread& mRenderThread;
-    Caches* mCaches = nullptr;
 
     std::set<Layer*> mActiveLayers;
     std::set<DeferredLayerUpdater*> mActiveLayerUpdaters;
diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp
deleted file mode 100644
index 470b4f5..0000000
--- a/libs/hwui/renderstate/TextureState.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2015 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 "renderstate/TextureState.h"
-
-#include "Caches.h"
-#include "utils/TraceUtils.h"
-
-#include <GLES3/gl3.h>
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-// Width of mShadowLutTexture, defines how accurate the shadow alpha lookup table is
-static const int SHADOW_LUT_SIZE = 128;
-
-// Must define as many texture units as specified by kTextureUnitsCount
-const GLenum kTextureUnits[] = {GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3};
-
-TextureState::TextureState() : mTextureUnit(0) {
-    glActiveTexture(kTextureUnits[0]);
-    resetBoundTextures();
-
-    GLint maxTextureUnits;
-    glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
-    LOG_ALWAYS_FATAL_IF(maxTextureUnits < kTextureUnitsCount,
-                        "At least %d texture units are required!", kTextureUnitsCount);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-}
-
-TextureState::~TextureState() {
-    if (mShadowLutTexture != nullptr) {
-        mShadowLutTexture->deleteTexture();
-    }
-}
-
-/**
- * Maps shadow geometry 'alpha' varying (1 for darkest, 0 for transparent) to
- * darkness at that spot. Input values of 0->1 should be mapped within the same
- * range, but can affect the curve for a different visual falloff.
- *
- * This is used to populate the shadow LUT texture for quick lookup in the
- * shadow shader.
- */
-static float computeShadowOpacity(float ratio) {
-    // exponential falloff function provided by UX
-    float val = 1 - ratio;
-    return exp(-val * val * 4.0) - 0.018;
-}
-
-void TextureState::constructTexture(Caches& caches) {
-    if (mShadowLutTexture == nullptr) {
-        mShadowLutTexture.reset(new Texture(caches));
-
-        unsigned char bytes[SHADOW_LUT_SIZE];
-        for (int i = 0; i < SHADOW_LUT_SIZE; i++) {
-            float inputRatio = i / (SHADOW_LUT_SIZE - 1.0f);
-            bytes[i] = computeShadowOpacity(inputRatio) * 255;
-        }
-        mShadowLutTexture->upload(GL_ALPHA, SHADOW_LUT_SIZE, 1, GL_ALPHA, GL_UNSIGNED_BYTE, &bytes);
-        mShadowLutTexture->setFilter(GL_LINEAR);
-        mShadowLutTexture->setWrap(GL_CLAMP_TO_EDGE);
-    }
-}
-
-void TextureState::activateTexture(GLuint textureUnit) {
-    LOG_ALWAYS_FATAL_IF(textureUnit >= kTextureUnitsCount,
-                        "Tried to use texture unit index %d, only %d exist", textureUnit,
-                        kTextureUnitsCount);
-    if (mTextureUnit != textureUnit) {
-        glActiveTexture(kTextureUnits[textureUnit]);
-        mTextureUnit = textureUnit;
-    }
-}
-
-void TextureState::resetActiveTexture() {
-    mTextureUnit = -1;
-}
-
-void TextureState::bindTexture(GLuint texture) {
-    if (mBoundTextures[mTextureUnit] != texture) {
-        glBindTexture(GL_TEXTURE_2D, texture);
-        mBoundTextures[mTextureUnit] = texture;
-    }
-}
-
-void TextureState::bindTexture(GLenum target, GLuint texture) {
-    if (target == GL_TEXTURE_2D) {
-        bindTexture(texture);
-    } else {
-        // GLConsumer directly calls glBindTexture() with
-        // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
-        // since the cached state could be stale
-        glBindTexture(target, texture);
-    }
-}
-
-void TextureState::deleteTexture(GLuint texture) {
-    // When glDeleteTextures() is called on a currently bound texture,
-    // OpenGL ES specifies that the texture is then considered unbound
-    // Consider the following series of calls:
-    //
-    // glGenTextures -> creates texture name 2
-    // glBindTexture(2)
-    // glDeleteTextures(2) -> 2 is now unbound
-    // glGenTextures -> can return 2 again
-    //
-    // If we don't call glBindTexture(2) after the second glGenTextures
-    // call, any texture operation will be performed on the default
-    // texture (name=0)
-
-    unbindTexture(texture);
-
-    glDeleteTextures(1, &texture);
-}
-
-void TextureState::resetBoundTextures() {
-    for (int i = 0; i < kTextureUnitsCount; i++) {
-        mBoundTextures[i] = 0;
-    }
-}
-
-void TextureState::unbindTexture(GLuint texture) {
-    for (int i = 0; i < kTextureUnitsCount; i++) {
-        if (mBoundTextures[i] == texture) {
-            mBoundTextures[i] = 0;
-        }
-    }
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h
deleted file mode 100644
index f1996d4..0000000
--- a/libs/hwui/renderstate/TextureState.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef RENDERSTATE_TEXTURESTATE_H
-#define RENDERSTATE_TEXTURESTATE_H
-
-#include "Texture.h"
-#include "Vertex.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-class Texture;
-
-class TextureState {
-    friend class Caches;  // TODO: move to RenderState
-public:
-    void constructTexture(Caches& caches);
-
-    /**
-     * Activate the specified texture unit. The texture unit must
-     * be specified using an integer number (0 for GL_TEXTURE0 etc.)
-     */
-    void activateTexture(GLuint textureUnit);
-
-    /**
-     * Invalidate the cached value of the active texture unit.
-     */
-    void resetActiveTexture();
-
-    /**
-     * Binds the specified texture as a GL_TEXTURE_2D texture.
-     * All texture bindings must be performed with this method or
-     * bindTexture(GLenum, GLuint).
-     */
-    void bindTexture(GLuint texture);
-
-    /**
-     * Binds the specified texture with the specified render target.
-     * All texture bindings must be performed with this method or
-     * bindTexture(GLuint).
-     */
-    void bindTexture(GLenum target, GLuint texture);
-
-    /**
-     * Deletes the specified texture and clears it from the cache
-     * of bound textures.
-     * All textures must be deleted using this method.
-     */
-    void deleteTexture(GLuint texture);
-
-    /**
-     * Signals that the cache of bound textures should be cleared.
-     * Other users of the context may have altered which textures are bound.
-     */
-    void resetBoundTextures();
-
-    /**
-     * Clear the cache of bound textures.
-     */
-    void unbindTexture(GLuint texture);
-
-    Texture* getShadowLutTexture() { return mShadowLutTexture.get(); }
-
-private:
-    // total number of texture units available for use
-    static const int kTextureUnitsCount = 4;
-
-    TextureState();
-    ~TextureState();
-    GLuint mTextureUnit;
-
-    // Caches texture bindings for the GL_TEXTURE_2D target
-    GLuint mBoundTextures[kTextureUnitsCount];
-
-    std::unique_ptr<Texture> mShadowLutTexture;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif  // RENDERSTATE_BLEND_H
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index bec80b1e..c45eeda 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -21,6 +21,7 @@
 #include "RenderThread.h"
 #include "pipeline/skia/ShaderCache.h"
 #include "pipeline/skia/SkiaMemoryTracer.h"
+#include "Properties.h"
 #include "renderstate/RenderState.h"
 
 #include <GrContextOptions.h>
@@ -214,11 +215,12 @@
             log.appendFormat("  Layer Info:\n");
         }
 
+        const char* layerType = Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL
+                ? "GlLayer" : "VkLayer";
         size_t layerMemoryTotal = 0;
         for (std::set<Layer*>::iterator it = renderState->mActiveLayers.begin();
              it != renderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
-            const char* layerType = layer->getApi() == Layer::Api::OpenGL ? "GlLayer" : "VkLayer";
             log.appendFormat("    %s size %dx%d\n", layerType, layer->getWidth(),
                              layer->getHeight());
             layerMemoryTotal += layer->getWidth() * layer->getHeight() * 4;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 5d72523..8b07d1d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -18,7 +18,6 @@
 #include <GpuMemoryTracker.h>
 
 #include "AnimationContext.h"
-#include "Caches.h"
 #include "EglManager.h"
 #include "Frame.h"
 #include "LayerUpdateQueue.h"
@@ -495,13 +494,6 @@
     }
 
     GpuMemoryTracker::onFrameCompleted();
-#ifdef BUGREPORT_FONT_CACHE_USAGE
-    auto renderType = Properties::getRenderPipelineType();
-    if (RenderPipelineType::OpenGL == renderType) {
-        Caches& caches = Caches::getInstance();
-        caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
-    }
-#endif
 }
 
 // Called by choreographer to do an RT-driven animation
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index cd21822..5f8d7ad 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -18,6 +18,7 @@
 
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <private/gui/SyncFeatures.h>
 #include <utils/Trace.h>
 #include "utils/StringUtils.h"
 
@@ -464,6 +465,109 @@
     return preserved;
 }
 
+status_t EglManager::fenceWait(sp<Fence>& fence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::fenceWait: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useWaitSync() &&
+        SyncFeatures::getInstance().useNativeFenceSync()) {
+        // Block GPU on the fence.
+        // Create an EGLSyncKHR from the current fence.
+        int fenceFd = fence->dup();
+        if (fenceFd == -1) {
+            ALOGE("EglManager::fenceWait: error dup'ing fence fd: %d", errno);
+            return -errno;
+        }
+        EGLint attribs[] = {
+            EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd,
+            EGL_NONE
+        };
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+        if (sync == EGL_NO_SYNC_KHR) {
+            close(fenceFd);
+            ALOGE("EglManager::fenceWait: error creating EGL fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+
+        // XXX: The spec draft is inconsistent as to whether this should
+        // return an EGLint or void.  Ignore the return value for now, as
+        // it's not strictly needed.
+        eglWaitSyncKHR(mEglDisplay, sync, 0);
+        EGLint eglErr = eglGetError();
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (eglErr != EGL_SUCCESS) {
+            ALOGE("EglManager::fenceWait: error waiting for EGL fence: %#x", eglErr);
+            return UNKNOWN_ERROR;
+        }
+    } else {
+        // Block CPU on the fence.
+        status_t err = fence->waitForever("EglManager::fenceWait");
+        if (err != NO_ERROR) {
+            ALOGE("EglManager::fenceWait: error waiting for fence: %d", err);
+            return err;
+        }
+    }
+    return OK;
+}
+
+status_t EglManager::createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence,
+        sp<Fence>& nativeFence) {
+    if (!hasEglContext()) {
+        ALOGE("EglManager::createReleaseFence: EGLDisplay not initialized");
+        return INVALID_OPERATION;
+    }
+
+    if (SyncFeatures::getInstance().useNativeFenceSync()) {
+        EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay,
+                EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+        if (sync == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating EGL fence: %#x",
+                    eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+        int fenceFd = eglDupNativeFenceFDANDROID(mEglDisplay, sync);
+        eglDestroySyncKHR(mEglDisplay, sync);
+        if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+            ALOGE("EglManager::createReleaseFence: error dup'ing native fence "
+                    "fd: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        nativeFence = new Fence(fenceFd);
+        *eglFence = EGL_NO_SYNC_KHR;
+    } else if (useFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+        if (*eglFence != EGL_NO_SYNC_KHR) {
+            // There is already a fence for the current slot.  We need to
+            // wait on that before replacing it with another fence to
+            // ensure that all outstanding buffer accesses have completed
+            // before the producer accesses it.
+            EGLint result = eglClientWaitSyncKHR(mEglDisplay, *eglFence, 0, 1000000000);
+            if (result == EGL_FALSE) {
+                ALOGE("EglManager::createReleaseFence: error waiting for previous fence: %#x",
+                        eglGetError());
+                return UNKNOWN_ERROR;
+            } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                ALOGE("EglManager::createReleaseFence: timeout waiting for previous fence");
+                return TIMED_OUT;
+            }
+            eglDestroySyncKHR(mEglDisplay, *eglFence);
+        }
+
+        // Create a fence for the outstanding accesses in the current
+        // OpenGL ES context.
+        *eglFence = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_FENCE_KHR, nullptr);
+        if (*eglFence == EGL_NO_SYNC_KHR) {
+            ALOGE("EglManager::createReleaseFence: error creating fence: %#x", eglGetError());
+            return UNKNOWN_ERROR;
+        }
+        glFlush();
+    }
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 8e8bb8b..507673a 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -17,8 +17,10 @@
 #define EGLMANAGER_H
 
 #include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <SkRect.h>
 #include <cutils/compiler.h>
+#include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
@@ -66,6 +68,14 @@
 
     EGLDisplay eglDisplay() const { return mEglDisplay; }
 
+    // Inserts a wait on fence command into the OpenGL ES command stream. If EGL extension
+    // support is missing, block the CPU on the fence.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending GL commands are flushed.
+    // Depending on installed extensions, the result is either Android native fence or EGL fence.
+    status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, sp<Fence>& nativeFence);
+
 private:
 
     void initExtensions();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index c1284ec..65f95ad 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -178,7 +178,7 @@
         return;
     }
     mEglManager->initialize();
-    renderState().onGLContextCreated();
+    renderState().onContextCreated();
 
 #ifdef HWUI_GLES_WRAP_ENABLED
     debug::GlesDriver* driver = debug::GlesDriver::get();
@@ -200,7 +200,7 @@
 void RenderThread::destroyGlContext() {
     if (mEglManager->hasEglContext()) {
         setGrContext(nullptr);
-        renderState().onGLContextDestroyed();
+        renderState().onContextDestroyed();
         mEglManager->destroy();
     }
 }
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1517f57..0c49dc0 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -40,7 +40,7 @@
 VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
 
 void VulkanManager::destroy() {
-    mRenderThread.renderState().onVkContextDestroyed();
+    mRenderThread.renderState().onContextDestroyed();
     mRenderThread.setGrContext(nullptr);
 
     if (VK_NULL_HANDLE != mCommandPool) {
@@ -404,7 +404,7 @@
         mSwapBehavior = SwapBehavior::BufferAge;
     }
 
-    mRenderThread.renderState().onVkContextCreated();
+    mRenderThread.renderState().onContextCreated();
 }
 
 // Returns the next BackbufferInfo to use for the next draw. The function will make sure all
@@ -981,6 +981,22 @@
     return surface->mCurrentTime - lastUsed;
 }
 
+status_t VulkanManager::fenceWait(sp<Fence>& fence) {
+    //TODO: Insert a wait on fence command into the Vulkan command buffer.
+    // Block CPU on the fence.
+    status_t err = fence->waitForever("VulkanManager::fenceWait");
+    if (err != NO_ERROR) {
+        ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
+        return err;
+    }
+    return OK;
+}
+
+status_t VulkanManager::createReleaseFence(sp<Fence>& nativeFence) {
+    //TODO: Create a fence that is signaled, when all the pending Vulkan commands are flushed.
+    return OK;
+}
+
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 5524c39..ebc11a5 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -23,6 +23,8 @@
 #include <vulkan/vulkan.h>
 
 #include <SkSurface.h>
+#include <ui/Fence.h>
+#include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
 
 class GrVkExtensions;
@@ -110,6 +112,12 @@
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
 
+    // Inserts a wait on fence command into the Vulkan command buffer.
+    status_t fenceWait(sp<Fence>& fence);
+
+    // Creates a fence that is signaled, when all the pending Vulkan commands are flushed.
+    status_t createReleaseFence(sp<Fence>& nativeFence);
+
 private:
     friend class RenderThread;
 
diff --git a/libs/hwui/surfacetexture/EGLConsumer.cpp b/libs/hwui/surfacetexture/EGLConsumer.cpp
new file mode 100644
index 0000000..c8220c6
--- /dev/null
+++ b/libs/hwui/surfacetexture/EGLConsumer.cpp
@@ -0,0 +1,675 @@
+/*
+ * 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.
+ */
+
+#include <inttypes.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <cutils/compiler.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <private/gui/SyncFeatures.h>
+#include "EGLConsumer.h"
+#include "SurfaceTexture.h"
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+namespace android {
+
+// Macros for including the SurfaceTexture name in log messages
+#define EGC_LOGV(x, ...) ALOGV("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGD(x, ...) ALOGD("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGW(x, ...) ALOGW("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+#define EGC_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+
+static const struct {
+    uint32_t width, height;
+    char const* bits;
+} kDebugData = {15, 12,
+                "_______________"
+                "_______________"
+                "_____XX_XX_____"
+                "__X_X_____X_X__"
+                "__X_XXXXXXX_X__"
+                "__XXXXXXXXXXX__"
+                "___XX_XXX_XX___"
+                "____XXXXXXX____"
+                "_____X___X_____"
+                "____X_____X____"
+                "_______________"
+                "_______________"};
+
+Mutex EGLConsumer::sStaticInitLock;
+sp<GraphicBuffer> EGLConsumer::sReleasedTexImageBuffer;
+
+static bool hasEglProtectedContentImpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen + 1);
+    bool atEnd = (cropExtLen + 1) < extsLen &&
+                 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen + 1));
+    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
+static bool hasEglProtectedContent() {
+    // Only compute whether the extension is present once the first time this
+    // function is called.
+    static bool hasIt = hasEglProtectedContentImpl();
+    return hasIt;
+}
+
+EGLConsumer::EGLConsumer() : mEglDisplay(EGL_NO_DISPLAY), mEglContext(EGL_NO_CONTEXT) {}
+
+status_t EGLConsumer::updateTexImage(SurfaceTexture& st) {
+    // Make sure the EGL state is the same as in previous calls.
+    status_t err = checkAndUpdateEglStateLocked(st);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    BufferItem item;
+
+    // Acquire the next buffer.
+    // In asynchronous mode the list is guaranteed to be one buffer
+    // deep, while in synchronous mode we use the oldest buffer.
+    err = st.acquireBufferLocked(&item, 0);
+    if (err != NO_ERROR) {
+        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+            // We always bind the texture even if we don't update its contents.
+            EGC_LOGV("updateTexImage: no buffers were available");
+            glBindTexture(st.mTexTarget, st.mTexName);
+            err = NO_ERROR;
+        } else {
+            EGC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
+        }
+        return err;
+    }
+
+    // Release the previous buffer.
+    err = updateAndReleaseLocked(item, nullptr, st);
+    if (err != NO_ERROR) {
+        // We always bind the texture.
+        glBindTexture(st.mTexTarget, st.mTexName);
+        return err;
+    }
+
+    // Bind the new buffer to the GL texture, and wait until it's ready.
+    return bindTextureImageLocked(st);
+}
+
+status_t EGLConsumer::releaseTexImage(SurfaceTexture& st) {
+    // Make sure the EGL state is the same as in previous calls.
+    status_t err = NO_ERROR;
+
+    // if we're detached, no need to validate EGL's state -- we won't use it.
+    if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+        err = checkAndUpdateEglStateLocked(st, true);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+
+    // Update the EGLConsumer state.
+    int buf = st.mCurrentTexture;
+    if (buf != BufferQueue::INVALID_BUFFER_SLOT) {
+        EGC_LOGV("releaseTexImage: (slot=%d, mOpMode=%d)", buf, (int)st.mOpMode);
+
+        // if we're detached, we just use the fence that was created in detachFromContext()
+        // so... basically, nothing more to do here.
+        if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+            // Do whatever sync ops we need to do before releasing the slot.
+            err = syncForReleaseLocked(mEglDisplay, st);
+            if (err != NO_ERROR) {
+                EGC_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err);
+                return err;
+            }
+        }
+
+        err = st.releaseBufferLocked(buf, st.mSlots[buf].mGraphicBuffer, mEglDisplay,
+                                     EGL_NO_SYNC_KHR);
+        if (err < NO_ERROR) {
+            EGC_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err);
+            return err;
+        }
+
+        if (mReleasedTexImage == nullptr) {
+            mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
+        }
+
+        st.mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
+        mCurrentTextureImage = mReleasedTexImage;
+        st.mCurrentCrop.makeInvalid();
+        st.mCurrentTransform = 0;
+        st.mCurrentTimestamp = 0;
+        st.mCurrentDataSpace = HAL_DATASPACE_UNKNOWN;
+        st.mCurrentFence = Fence::NO_FENCE;
+        st.mCurrentFenceTime = FenceTime::NO_FENCE;
+
+        // detached, don't touch the texture (and we may not even have an
+        // EGLDisplay here.
+        if (st.mOpMode == SurfaceTexture::OpMode::attachedToGL) {
+            // This binds a dummy buffer (mReleasedTexImage).
+            status_t result = bindTextureImageLocked(st);
+            if (result != NO_ERROR) {
+                return result;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+sp<GraphicBuffer> EGLConsumer::getDebugTexImageBuffer() {
+    Mutex::Autolock _l(sStaticInitLock);
+    if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
+        // The first time, create the debug texture in case the application
+        // continues to use it.
+        sp<GraphicBuffer> buffer = new GraphicBuffer(
+                kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
+                GraphicBuffer::USAGE_SW_WRITE_RARELY, "[EGLConsumer debug texture]");
+        uint32_t* bits;
+        buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
+        uint32_t stride = buffer->getStride();
+        uint32_t height = buffer->getHeight();
+        memset(bits, 0, stride * height * 4);
+        for (uint32_t y = 0; y < kDebugData.height; y++) {
+            for (uint32_t x = 0; x < kDebugData.width; x++) {
+                bits[x] = (kDebugData.bits[y + kDebugData.width + x] == 'X') ? 0xFF000000
+                                                                             : 0xFFFFFFFF;
+            }
+            bits += stride;
+        }
+        buffer->unlock();
+        sReleasedTexImageBuffer = buffer;
+    }
+    return sReleasedTexImageBuffer;
+}
+
+void EGLConsumer::onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st) {
+    // If item->mGraphicBuffer is not null, this buffer has not been acquired
+    // before, so any prior EglImage created is using a stale buffer. This
+    // replaces any old EglImage with a new one (using the new buffer).
+    int slot = item->mSlot;
+    if (item->mGraphicBuffer != nullptr || mEglSlots[slot].mEglImage.get() == nullptr) {
+        mEglSlots[slot].mEglImage = new EglImage(st.mSlots[slot].mGraphicBuffer);
+    }
+}
+
+void EGLConsumer::onReleaseBufferLocked(int buf) {
+    mEglSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+}
+
+status_t EGLConsumer::updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
+                                             SurfaceTexture& st) {
+    status_t err = NO_ERROR;
+
+    int slot = item.mSlot;
+
+    if (st.mOpMode != SurfaceTexture::OpMode::attachedToGL) {
+        EGC_LOGE(
+                "updateAndRelease: EGLConsumer is not attached to an OpenGL "
+                "ES context");
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return INVALID_OPERATION;
+    }
+
+    // Confirm state.
+    err = checkAndUpdateEglStateLocked(st);
+    if (err != NO_ERROR) {
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return err;
+    }
+
+    // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
+    // if nessessary, for the gralloc buffer currently in the slot in
+    // ConsumerBase.
+    // We may have to do this even when item.mGraphicBuffer == NULL (which
+    // means the buffer was previously acquired).
+    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay);
+    if (err != NO_ERROR) {
+        EGC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
+                 slot);
+        st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR);
+        return UNKNOWN_ERROR;
+    }
+
+    // Do whatever sync ops we need to do before releasing the old slot.
+    if (slot != st.mCurrentTexture) {
+        err = syncForReleaseLocked(mEglDisplay, st);
+        if (err != NO_ERROR) {
+            // Release the buffer we just acquired.  It's not safe to
+            // release the old buffer, so instead we just drop the new frame.
+            // As we are still under lock since acquireBuffer, it is safe to
+            // release by slot.
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, mEglDisplay,
+                                   EGL_NO_SYNC_KHR);
+            return err;
+        }
+    }
+
+    EGC_LOGV(
+            "updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", st.mCurrentTexture,
+            mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : nullptr,
+            slot, st.mSlots[slot].mGraphicBuffer->handle);
+
+    // Hang onto the pointer so that it isn't freed in the call to
+    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
+    // the same.
+    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
+
+    // release old buffer
+    if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        if (pendingRelease == nullptr) {
+            status_t status = st.releaseBufferLocked(
+                    st.mCurrentTexture, mCurrentTextureImage->graphicBuffer(), mEglDisplay,
+                    mEglSlots[st.mCurrentTexture].mEglFence);
+            if (status < NO_ERROR) {
+                EGC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
+                         status);
+                err = status;
+                // keep going, with error raised [?]
+            }
+        } else {
+            pendingRelease->currentTexture = st.mCurrentTexture;
+            pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
+            pendingRelease->display = mEglDisplay;
+            pendingRelease->fence = mEglSlots[st.mCurrentTexture].mEglFence;
+            pendingRelease->isPending = true;
+        }
+    }
+
+    // Update the EGLConsumer state.
+    st.mCurrentTexture = slot;
+    mCurrentTextureImage = nextTextureImage;
+    st.mCurrentCrop = item.mCrop;
+    st.mCurrentTransform = item.mTransform;
+    st.mCurrentScalingMode = item.mScalingMode;
+    st.mCurrentTimestamp = item.mTimestamp;
+    st.mCurrentDataSpace = item.mDataSpace;
+    st.mCurrentFence = item.mFence;
+    st.mCurrentFenceTime = item.mFenceTime;
+    st.mCurrentFrameNumber = item.mFrameNumber;
+
+    st.computeCurrentTransformMatrixLocked();
+
+    return err;
+}
+
+status_t EGLConsumer::bindTextureImageLocked(SurfaceTexture& st) {
+    if (mEglDisplay == EGL_NO_DISPLAY) {
+        ALOGE("bindTextureImage: invalid display");
+        return INVALID_OPERATION;
+    }
+
+    GLenum error;
+    while ((error = glGetError()) != GL_NO_ERROR) {
+        EGC_LOGW("bindTextureImage: clearing GL error: %#04x", error);
+    }
+
+    glBindTexture(st.mTexTarget, st.mTexName);
+    if (st.mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
+        EGC_LOGE("bindTextureImage: no currently-bound texture");
+        return NO_INIT;
+    }
+
+    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay);
+    if (err != NO_ERROR) {
+        EGC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
+                 st.mCurrentTexture);
+        return UNKNOWN_ERROR;
+    }
+    mCurrentTextureImage->bindToTextureTarget(st.mTexTarget);
+
+    // In the rare case that the display is terminated and then initialized
+    // again, we can't detect that the display changed (it didn't), but the
+    // image is invalid. In this case, repeat the exact same steps while
+    // forcing the creation of a new image.
+    if ((error = glGetError()) != GL_NO_ERROR) {
+        glBindTexture(st.mTexTarget, st.mTexName);
+        status_t result = mCurrentTextureImage->createIfNeeded(mEglDisplay, true);
+        if (result != NO_ERROR) {
+            EGC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
+                     st.mCurrentTexture);
+            return UNKNOWN_ERROR;
+        }
+        mCurrentTextureImage->bindToTextureTarget(st.mTexTarget);
+        if ((error = glGetError()) != GL_NO_ERROR) {
+            EGC_LOGE("bindTextureImage: error binding external image: %#04x", error);
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    // Wait for the new buffer to be ready.
+    return doGLFenceWaitLocked(st);
+}
+
+status_t EGLConsumer::checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck) {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (!contextCheck) {
+        // if this is the first time we're called, mEglDisplay/mEglContext have
+        // never been set, so don't error out (below).
+        if (mEglDisplay == EGL_NO_DISPLAY) {
+            mEglDisplay = dpy;
+        }
+        if (mEglContext == EGL_NO_CONTEXT) {
+            mEglContext = ctx;
+        }
+    }
+
+    if (mEglDisplay != dpy || dpy == EGL_NO_DISPLAY) {
+        EGC_LOGE("checkAndUpdateEglState: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx || ctx == EGL_NO_CONTEXT) {
+        EGC_LOGE("checkAndUpdateEglState: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    mEglDisplay = dpy;
+    mEglContext = ctx;
+    return NO_ERROR;
+}
+
+status_t EGLConsumer::detachFromContext(SurfaceTexture& st) {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
+        EGC_LOGE("detachFromContext: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
+        EGC_LOGE("detachFromContext: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
+        status_t err = syncForReleaseLocked(dpy, st);
+        if (err != OK) {
+            return err;
+        }
+
+        glDeleteTextures(1, &st.mTexName);
+    }
+
+    mEglDisplay = EGL_NO_DISPLAY;
+    mEglContext = EGL_NO_CONTEXT;
+
+    return OK;
+}
+
+status_t EGLConsumer::attachToContext(uint32_t tex, SurfaceTexture& st) {
+    // Initialize mCurrentTextureImage if there is a current buffer from past attached state.
+    int slot = st.mCurrentTexture;
+    if (slot != BufferItem::INVALID_BUFFER_SLOT) {
+        if (!mEglSlots[slot].mEglImage.get()) {
+            mEglSlots[slot].mEglImage = new EglImage(st.mSlots[slot].mGraphicBuffer);
+        }
+        mCurrentTextureImage = mEglSlots[slot].mEglImage;
+    }
+
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (dpy == EGL_NO_DISPLAY) {
+        EGC_LOGE("attachToContext: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (ctx == EGL_NO_CONTEXT) {
+        EGC_LOGE("attachToContext: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    // We need to bind the texture regardless of whether there's a current
+    // buffer.
+    glBindTexture(st.mTexTarget, GLuint(tex));
+
+    mEglDisplay = dpy;
+    mEglContext = ctx;
+    st.mTexName = tex;
+    st.mOpMode = SurfaceTexture::OpMode::attachedToGL;
+
+    if (mCurrentTextureImage != nullptr) {
+        // This may wait for a buffer a second time. This is likely required if
+        // this is a different context, since otherwise the wait could be skipped
+        // by bouncing through another context. For the same context the extra
+        // wait is redundant.
+        status_t err = bindTextureImageLocked(st);
+        if (err != NO_ERROR) {
+            return err;
+        }
+    }
+
+    return OK;
+}
+
+status_t EGLConsumer::syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st) {
+    EGC_LOGV("syncForReleaseLocked");
+
+    if (st.mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        if (SyncFeatures::getInstance().useNativeFenceSync()) {
+            EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+            if (sync == EGL_NO_SYNC_KHR) {
+                EGC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            glFlush();
+            int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
+            eglDestroySyncKHR(dpy, sync);
+            if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+                EGC_LOGE(
+                        "syncForReleaseLocked: error dup'ing native fence "
+                        "fd: %#x",
+                        eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            sp<Fence> fence(new Fence(fenceFd));
+            status_t err = st.addReleaseFenceLocked(st.mCurrentTexture,
+                                                    mCurrentTextureImage->graphicBuffer(), fence);
+            if (err != OK) {
+                EGC_LOGE(
+                        "syncForReleaseLocked: error adding release fence: "
+                        "%s (%d)",
+                        strerror(-err), err);
+                return err;
+            }
+        } else if (st.mUseFenceSync && SyncFeatures::getInstance().useFenceSync()) {
+            EGLSyncKHR fence = mEglSlots[st.mCurrentTexture].mEglFence;
+            if (fence != EGL_NO_SYNC_KHR) {
+                // There is already a fence for the current slot.  We need to
+                // wait on that before replacing it with another fence to
+                // ensure that all outstanding buffer accesses have completed
+                // before the producer accesses it.
+                EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
+                if (result == EGL_FALSE) {
+                    EGC_LOGE(
+                            "syncForReleaseLocked: error waiting for previous "
+                            "fence: %#x",
+                            eglGetError());
+                    return UNKNOWN_ERROR;
+                } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                    EGC_LOGE(
+                            "syncForReleaseLocked: timeout waiting for previous "
+                            "fence");
+                    return TIMED_OUT;
+                }
+                eglDestroySyncKHR(dpy, fence);
+            }
+
+            // Create a fence for the outstanding accesses in the current
+            // OpenGL ES context.
+            fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
+            if (fence == EGL_NO_SYNC_KHR) {
+                EGC_LOGE("syncForReleaseLocked: error creating fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+            glFlush();
+            mEglSlots[st.mCurrentTexture].mEglFence = fence;
+        }
+    }
+
+    return OK;
+}
+
+status_t EGLConsumer::doGLFenceWaitLocked(SurfaceTexture& st) const {
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    EGLContext ctx = eglGetCurrentContext();
+
+    if (mEglDisplay != dpy || mEglDisplay == EGL_NO_DISPLAY) {
+        EGC_LOGE("doGLFenceWait: invalid current EGLDisplay");
+        return INVALID_OPERATION;
+    }
+
+    if (mEglContext != ctx || mEglContext == EGL_NO_CONTEXT) {
+        EGC_LOGE("doGLFenceWait: invalid current EGLContext");
+        return INVALID_OPERATION;
+    }
+
+    if (st.mCurrentFence->isValid()) {
+        if (SyncFeatures::getInstance().useWaitSync() &&
+            SyncFeatures::getInstance().useNativeFenceSync()) {
+            // Create an EGLSyncKHR from the current fence.
+            int fenceFd = st.mCurrentFence->dup();
+            if (fenceFd == -1) {
+                EGC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
+                return -errno;
+            }
+            EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+            EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+            if (sync == EGL_NO_SYNC_KHR) {
+                close(fenceFd);
+                EGC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
+                return UNKNOWN_ERROR;
+            }
+
+            // XXX: The spec draft is inconsistent as to whether this should
+            // return an EGLint or void.  Ignore the return value for now, as
+            // it's not strictly needed.
+            eglWaitSyncKHR(dpy, sync, 0);
+            EGLint eglErr = eglGetError();
+            eglDestroySyncKHR(dpy, sync);
+            if (eglErr != EGL_SUCCESS) {
+                EGC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
+                return UNKNOWN_ERROR;
+            }
+        } else {
+            status_t err = st.mCurrentFence->waitForever("EGLConsumer::doGLFenceWaitLocked");
+            if (err != NO_ERROR) {
+                EGC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
+                return err;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+void EGLConsumer::onFreeBufferLocked(int slotIndex) {
+    mEglSlots[slotIndex].mEglImage.clear();
+}
+
+void EGLConsumer::onAbandonLocked() {
+    mCurrentTextureImage.clear();
+}
+
+EGLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
+        : mGraphicBuffer(graphicBuffer), mEglImage(EGL_NO_IMAGE_KHR), mEglDisplay(EGL_NO_DISPLAY) {}
+
+EGLConsumer::EglImage::~EglImage() {
+    if (mEglImage != EGL_NO_IMAGE_KHR) {
+        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
+            ALOGE("~EglImage: eglDestroyImageKHR failed");
+        }
+        eglTerminate(mEglDisplay);
+    }
+}
+
+status_t EGLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, bool forceCreation) {
+    // If there's an image and it's no longer valid, destroy it.
+    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
+    bool displayInvalid = mEglDisplay != eglDisplay;
+    if (haveImage && (displayInvalid || forceCreation)) {
+        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
+            ALOGE("createIfNeeded: eglDestroyImageKHR failed");
+        }
+        eglTerminate(mEglDisplay);
+        mEglImage = EGL_NO_IMAGE_KHR;
+        mEglDisplay = EGL_NO_DISPLAY;
+    }
+
+    // If there's no image, create one.
+    if (mEglImage == EGL_NO_IMAGE_KHR) {
+        mEglDisplay = eglDisplay;
+        mEglImage = createImage(mEglDisplay, mGraphicBuffer);
+    }
+
+    // Fail if we can't create a valid image.
+    if (mEglImage == EGL_NO_IMAGE_KHR) {
+        mEglDisplay = EGL_NO_DISPLAY;
+        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+              buffer->getPixelFormat());
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+void EGLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
+    glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
+}
+
+EGLImageKHR EGLConsumer::EglImage::createImage(EGLDisplay dpy,
+                                               const sp<GraphicBuffer>& graphicBuffer) {
+    EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+    const bool createProtectedImage =
+            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
+    EGLint attrs[] = {
+            EGL_IMAGE_PRESERVED_KHR,
+            EGL_TRUE,
+            createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+            createProtectedImage ? EGL_TRUE : EGL_NONE,
+            EGL_NONE,
+    };
+    eglInitialize(dpy, nullptr, nullptr);
+    EGLImageKHR image =
+            eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
+    if (image == EGL_NO_IMAGE_KHR) {
+        EGLint error = eglGetError();
+        ALOGE("error creating EGLImage: %#x", error);
+        eglTerminate(dpy);
+    }
+    return image;
+}
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/EGLConsumer.h b/libs/hwui/surfacetexture/EGLConsumer.h
new file mode 100644
index 0000000..eccb082
--- /dev/null
+++ b/libs/hwui/surfacetexture/EGLConsumer.h
@@ -0,0 +1,311 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <gui/BufferQueueDefs.h>
+
+#include <ui/FenceTime.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+class SurfaceTexture;
+
+/*
+ * EGLConsumer implements the parts of SurfaceTexture that deal with
+ * textures attached to an GL context.
+ */
+class EGLConsumer {
+public:
+    EGLConsumer();
+
+    /**
+     * updateTexImage acquires the most recently queued buffer, and sets the
+     * image contents of the target texture to it.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     *
+     * This calls doGLFenceWait to ensure proper synchronization.
+     */
+    status_t updateTexImage(SurfaceTexture& st);
+
+    /*
+     * releaseTexImage releases the texture acquired in updateTexImage().
+     * This is intended to be used in single buffer mode.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     */
+    status_t releaseTexImage(SurfaceTexture& st);
+
+    /**
+     * detachFromContext detaches the EGLConsumer from the calling thread's
+     * current OpenGL ES context.  This context must be the same as the context
+     * that was current for previous calls to updateTexImage.
+     *
+     * Detaching a EGLConsumer from an OpenGL ES context will result in the
+     * deletion of the OpenGL ES texture object into which the images were being
+     * streamed.  After a EGLConsumer has been detached from the OpenGL ES
+     * context calls to updateTexImage will fail returning INVALID_OPERATION
+     * until the EGLConsumer is attached to a new OpenGL ES context using the
+     * attachToContext method.
+     */
+    status_t detachFromContext(SurfaceTexture& st);
+
+    /**
+     * attachToContext attaches a EGLConsumer that is currently in the
+     * 'detached' state to the current OpenGL ES context.  A EGLConsumer is
+     * in the 'detached' state iff detachFromContext has successfully been
+     * called and no calls to attachToContext have succeeded since the last
+     * detachFromContext call.  Calls to attachToContext made on a
+     * EGLConsumer that is not in the 'detached' state will result in an
+     * INVALID_OPERATION error.
+     *
+     * The tex argument specifies the OpenGL ES texture object name in the
+     * new context into which the image contents will be streamed.  A successful
+     * call to attachToContext will result in this texture object being bound to
+     * the texture target and populated with the image contents that were
+     * current at the time of the last call to detachFromContext.
+     */
+    status_t attachToContext(uint32_t tex, SurfaceTexture& st);
+
+    /**
+     * onAcquireBufferLocked amends the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase behavior.
+     */
+    void onAcquireBufferLocked(BufferItem* item, SurfaceTexture& st);
+
+    /**
+     * onReleaseBufferLocked amends the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase.
+     */
+    void onReleaseBufferLocked(int slot);
+
+    /**
+     * onFreeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
+     */
+    void onFreeBufferLocked(int slotIndex);
+
+    /**
+     * onAbandonLocked amends the ConsumerBase method to clear
+     * mCurrentTextureImage in addition to the ConsumerBase behavior.
+     */
+    void onAbandonLocked();
+
+protected:
+    struct PendingRelease {
+        PendingRelease()
+                : isPending(false)
+                , currentTexture(-1)
+                , graphicBuffer()
+                , display(nullptr)
+                , fence(nullptr) {}
+
+        bool isPending;
+        int currentTexture;
+        sp<GraphicBuffer> graphicBuffer;
+        EGLDisplay display;
+        EGLSyncKHR fence;
+    };
+
+    /**
+     * This releases the buffer in the slot referenced by mCurrentTexture,
+     * then updates state to refer to the BufferItem, which must be a
+     * newly-acquired buffer. If pendingRelease is not null, the parameters
+     * which would have been passed to releaseBufferLocked upon the successful
+     * completion of the method will instead be returned to the caller, so that
+     * it may call releaseBufferLocked itself later.
+     */
+    status_t updateAndReleaseLocked(const BufferItem& item, PendingRelease* pendingRelease,
+                                    SurfaceTexture& st);
+
+    /**
+     * Binds mTexName and the current buffer to mTexTarget.  Uses
+     * mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
+     * bind succeeds, this calls doGLFenceWait.
+     */
+    status_t bindTextureImageLocked(SurfaceTexture& st);
+
+    /**
+     * Gets the current EGLDisplay and EGLContext values, and compares them
+     * to mEglDisplay and mEglContext.  If the fields have been previously
+     * set, the values must match; if not, the fields are set to the current
+     * values.
+     * The contextCheck argument is used to ensure that a GL context is
+     * properly set; when set to false, the check is not performed.
+     */
+    status_t checkAndUpdateEglStateLocked(SurfaceTexture& st, bool contextCheck = false);
+
+    /**
+     * EglImage is a utility class for tracking and creating EGLImageKHRs. There
+     * is primarily just one image per slot, but there is also special cases:
+     *  - For releaseTexImage, we use a debug image (mReleasedTexImage)
+     *  - After freeBuffer, we must still keep the current image/buffer
+     * Reference counting EGLImages lets us handle all these cases easily while
+     * also only creating new EGLImages from buffers when required.
+     */
+    class EglImage : public LightRefBase<EglImage> {
+    public:
+        EglImage(sp<GraphicBuffer> graphicBuffer);
+
+        /**
+         * createIfNeeded creates an EGLImage if required (we haven't created
+         * one yet, or the EGLDisplay or crop-rect has changed).
+         */
+        status_t createIfNeeded(EGLDisplay display, bool forceCreate = false);
+
+        /**
+         * This calls glEGLImageTargetTexture2DOES to bind the image to the
+         * texture in the specified texture target.
+         */
+        void bindToTextureTarget(uint32_t texTarget);
+
+        const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
+        const native_handle* graphicBufferHandle() {
+            return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
+        }
+
+    private:
+        // Only allow instantiation using ref counting.
+        friend class LightRefBase<EglImage>;
+        virtual ~EglImage();
+
+        // createImage creates a new EGLImage from a GraphicBuffer.
+        EGLImageKHR createImage(EGLDisplay dpy, const sp<GraphicBuffer>& graphicBuffer);
+
+        // Disallow copying
+        EglImage(const EglImage& rhs);
+        void operator=(const EglImage& rhs);
+
+        // mGraphicBuffer is the buffer that was used to create this image.
+        sp<GraphicBuffer> mGraphicBuffer;
+
+        // mEglImage is the EGLImage created from mGraphicBuffer.
+        EGLImageKHR mEglImage;
+
+        // mEGLDisplay is the EGLDisplay that was used to create mEglImage.
+        EGLDisplay mEglDisplay;
+
+        // mCropRect is the crop rectangle passed to EGL when mEglImage
+        // was created.
+        Rect mCropRect;
+    };
+
+    /**
+     * doGLFenceWaitLocked inserts a wait command into the OpenGL ES command
+     * stream to ensure that it is safe for future OpenGL ES commands to
+     * access the current texture buffer.
+     */
+    status_t doGLFenceWaitLocked(SurfaceTexture& st) const;
+
+    /**
+     * syncForReleaseLocked performs the synchronization needed to release the
+     * current slot from an OpenGL ES context.  If needed it will set the
+     * current slot's fence to guard against a producer accessing the buffer
+     * before the outstanding accesses have completed.
+     */
+    status_t syncForReleaseLocked(EGLDisplay dpy, SurfaceTexture& st);
+
+    /**
+     * returns a graphic buffer used when the texture image has been released
+     */
+    static sp<GraphicBuffer> getDebugTexImageBuffer();
+
+    /**
+     * The default consumer usage flags that EGLConsumer always sets on its
+     * BufferQueue instance; these will be OR:d with any additional flags passed
+     * from the EGLConsumer user. In particular, EGLConsumer will always
+     * consume buffers as hardware textures.
+     */
+    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+
+    /**
+     * mCurrentTextureImage is the EglImage/buffer of the current texture. It's
+     * possible that this buffer is not associated with any buffer slot, so we
+     * must track it separately in order to support the getCurrentBuffer method.
+     */
+    sp<EglImage> mCurrentTextureImage;
+
+    /**
+     * EGLSlot contains the information and object references that
+     * EGLConsumer maintains about a BufferQueue buffer slot.
+     */
+    struct EglSlot {
+        EglSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+
+        /**
+         * mEglImage is the EGLImage created from mGraphicBuffer.
+         */
+        sp<EglImage> mEglImage;
+
+        /**
+         * mFence is the EGL sync object that must signal before the buffer
+         * associated with this buffer slot may be dequeued. It is initialized
+         * to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
+         * on a compile-time option) set to a new sync object in updateTexImage.
+         */
+        EGLSyncKHR mEglFence;
+    };
+
+    /**
+     * mEglDisplay is the EGLDisplay with which this EGLConsumer is currently
+     * associated.  It is intialized to EGL_NO_DISPLAY and gets set to the
+     * current display when updateTexImage is called for the first time and when
+     * attachToContext is called.
+     */
+    EGLDisplay mEglDisplay;
+
+    /**
+     * mEglContext is the OpenGL ES context with which this EGLConsumer is
+     * currently associated.  It is initialized to EGL_NO_CONTEXT and gets set
+     * to the current GL context when updateTexImage is called for the first
+     * time and when attachToContext is called.
+     */
+    EGLContext mEglContext;
+
+    /**
+     * mEGLSlots stores the buffers that have been allocated by the BufferQueue
+     * for each buffer slot.  It is initialized to null pointers, and gets
+     * filled in with the result of BufferQueue::acquire when the
+     * client dequeues a buffer from a
+     * slot that has not yet been used. The buffer allocated to a slot will also
+     * be replaced if the requested buffer usage or geometry differs from that
+     * of the buffer allocated to a slot.
+     */
+    EglSlot mEglSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
+
+    /**
+     * protects static initialization
+     */
+    static Mutex sStaticInitLock;
+
+    /**
+     * mReleasedTexImageBuffer is a dummy buffer used when in single buffer
+     * mode and releaseTexImage() has been called
+     */
+    static sp<GraphicBuffer> sReleasedTexImageBuffer;
+    sp<EglImage> mReleasedTexImage;
+};
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp
new file mode 100644
index 0000000..c86cd96
--- /dev/null
+++ b/libs/hwui/surfacetexture/ImageConsumer.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#include "ImageConsumer.h"
+#include <gui/BufferQueue.h>
+#include "Properties.h"
+#include "SurfaceTexture.h"
+#include "renderstate/RenderState.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/RenderThread.h"
+#include "renderthread/VulkanManager.h"
+
+// Macro for including the SurfaceTexture name in log messages
+#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
+
+namespace android {
+
+void ImageConsumer::onFreeBufferLocked(int slotIndex) {
+    mImageSlots[slotIndex].mImage.reset();
+}
+
+void ImageConsumer::onAcquireBufferLocked(BufferItem* item) {
+    // If item->mGraphicBuffer is not null, this buffer has not been acquired
+    // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage.
+    if (item->mGraphicBuffer != nullptr) {
+        mImageSlots[item->mSlot].mImage.reset();
+    }
+}
+
+void ImageConsumer::onReleaseBufferLocked(int buf) {
+    mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
+}
+
+void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer) {
+    if (!mImage.get()) {
+        mImage = graphicBuffer.get()
+                         ? SkImage::MakeFromAHardwareBuffer(
+                                   reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
+                                   kPremul_SkAlphaType, SkColorSpace::MakeSRGB())
+                         : nullptr;
+    }
+}
+
+sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
+                                           uirenderer::RenderState& renderState) {
+    BufferItem item;
+    status_t err;
+    err = st.acquireBufferLocked(&item, 0);
+    if (err != OK) {
+        if (err != BufferQueue::NO_BUFFER_AVAILABLE) {
+            IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
+        } else {
+            int slot = st.mCurrentTexture;
+            if (slot != BufferItem::INVALID_BUFFER_SLOT) {
+                *queueEmpty = true;
+                mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+                return mImageSlots[slot].mImage;
+            }
+        }
+        return nullptr;
+    }
+
+    int slot = item.mSlot;
+    if (item.mFence->isValid()) {
+        // Wait on the producer fence for the buffer to be ready.
+        if (uirenderer::Properties::getRenderPipelineType() ==
+            uirenderer::RenderPipelineType::SkiaGL) {
+            err = renderState.getRenderThread().eglManager().fenceWait(item.mFence);
+        } else {
+            err = renderState.getRenderThread().vulkanManager().fenceWait(item.mFence);
+        }
+        if (err != OK) {
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                   EGL_NO_SYNC_KHR);
+            return nullptr;
+        }
+    }
+
+    // Release old buffer.
+    if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
+        // If needed, set the released slot's fence to guard against a producer accessing the
+        // buffer before the outstanding accesses have completed.
+        sp<Fence> releaseFence;
+        EGLDisplay display = EGL_NO_DISPLAY;
+        if (uirenderer::Properties::getRenderPipelineType() ==
+            uirenderer::RenderPipelineType::SkiaGL) {
+            auto& eglManager = renderState.getRenderThread().eglManager();
+            display = eglManager.eglDisplay();
+            err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence,
+                                                releaseFence);
+        } else {
+            err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
+        }
+        if (OK != err) {
+            st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                   EGL_NO_SYNC_KHR);
+            return nullptr;
+        }
+
+        if (releaseFence.get()) {
+            status_t err = st.addReleaseFenceLocked(
+                    st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence);
+            if (err != OK) {
+                IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
+                st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
+                                       EGL_NO_SYNC_KHR);
+                return nullptr;
+            }
+        }
+
+        // Finally release the old buffer.
+        status_t status = st.releaseBufferLocked(
+                st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
+                mImageSlots[st.mCurrentTexture].mEglFence);
+        if (status < NO_ERROR) {
+            IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
+            err = status;
+            // Keep going, with error raised.
+        }
+    }
+
+    // Update the state.
+    st.mCurrentTexture = slot;
+    st.mCurrentCrop = item.mCrop;
+    st.mCurrentTransform = item.mTransform;
+    st.mCurrentScalingMode = item.mScalingMode;
+    st.mCurrentTimestamp = item.mTimestamp;
+    st.mCurrentDataSpace = item.mDataSpace;
+    st.mCurrentFence = item.mFence;
+    st.mCurrentFenceTime = item.mFenceTime;
+    st.mCurrentFrameNumber = item.mFrameNumber;
+    st.computeCurrentTransformMatrixLocked();
+
+    *queueEmpty = false;
+    mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+    return mImageSlots[slot].mImage;
+}
+
+} /* namespace android */
diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h
new file mode 100644
index 0000000..31ee8db
--- /dev/null
+++ b/libs/hwui/surfacetexture/ImageConsumer.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <gui/BufferQueueDefs.h>
+
+#include <SkImage.h>
+#include <cutils/compiler.h>
+#include <gui/BufferItem.h>
+#include <system/graphics.h>
+
+namespace android {
+
+namespace uirenderer {
+class RenderState;
+}
+
+class SurfaceTexture;
+
+/*
+ * ImageConsumer implements the parts of SurfaceTexture that deal with
+ * images consumed by HWUI view system.
+ */
+class ImageConsumer {
+public:
+    sk_sp<SkImage> dequeueImage(bool* queueEmpty, SurfaceTexture& cb,
+                                uirenderer::RenderState& renderState);
+
+    /**
+     * onAcquireBufferLocked amends the ConsumerBase method to update the
+     * mImageSlots array in addition to the ConsumerBase behavior.
+     */
+    void onAcquireBufferLocked(BufferItem* item);
+
+    /**
+     * onReleaseBufferLocked amends the ConsumerBase method to update the
+     * mImageSlots array in addition to the ConsumerBase.
+     */
+    void onReleaseBufferLocked(int slot);
+
+    /**
+     * onFreeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the SkImage in that slot. Otherwise it has no effect.
+     */
+    void onFreeBufferLocked(int slotIndex);
+
+private:
+    /**
+     * ImageSlot contains the information and object references that
+     * ImageConsumer maintains about a BufferQueue buffer slot.
+     */
+    struct ImageSlot {
+        ImageSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+
+        // mImage is the SkImage created from mGraphicBuffer.
+        sk_sp<SkImage> mImage;
+
+        /**
+         * mEglFence is the EGL sync object that must signal before the buffer
+         * associated with this buffer slot may be dequeued.
+         */
+        EGLSyncKHR mEglFence;
+
+        void createIfNeeded(sp<GraphicBuffer> graphicBuffer);
+    };
+
+    /**
+     * ImageConsumer stores the SkImages that have been allocated by the BufferQueue
+     * for each buffer slot.  It is initialized to null pointers, and gets
+     * filled in with the result of BufferQueue::acquire when the
+     * client dequeues a buffer from a
+     * slot that has not yet been used. The buffer allocated to a slot will also
+     * be replaced if the requested buffer usage or geometry differs from that
+     * of the buffer allocated to a slot.
+     */
+    ImageSlot mImageSlots[BufferQueueDefs::NUM_BUFFER_SLOTS];
+};
+
+}; /* namespace android */
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.cpp b/libs/hwui/surfacetexture/SurfaceTexture.cpp
new file mode 100644
index 0000000..4bff715
--- /dev/null
+++ b/libs/hwui/surfacetexture/SurfaceTexture.cpp
@@ -0,0 +1,496 @@
+/*
+ * 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.
+ */
+
+#include <cutils/compiler.h>
+#include <gui/BufferQueue.h>
+#include <math/mat4.h>
+#include <system/window.h>
+
+#include <utils/Trace.h>
+
+#include "Matrix.h"
+#include "SurfaceTexture.h"
+
+namespace android {
+
+// Macros for including the SurfaceTexture name in log messages
+#define SFT_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define SFT_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
+
+static const mat4 mtxIdentity;
+
+SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
+                               uint32_t texTarget, bool useFenceSync, bool isControlledByApp)
+        : ConsumerBase(bq, isControlledByApp)
+        , mCurrentCrop(Rect::EMPTY_RECT)
+        , mCurrentTransform(0)
+        , mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE)
+        , mCurrentFence(Fence::NO_FENCE)
+        , mCurrentTimestamp(0)
+        , mCurrentDataSpace(HAL_DATASPACE_UNKNOWN)
+        , mCurrentFrameNumber(0)
+        , mDefaultWidth(1)
+        , mDefaultHeight(1)
+        , mFilteringEnabled(true)
+        , mTexName(tex)
+        , mUseFenceSync(useFenceSync)
+        , mTexTarget(texTarget)
+        , mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
+        , mOpMode(OpMode::attachedToGL) {
+    SFT_LOGV("SurfaceTexture");
+
+    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
+
+    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+}
+
+SurfaceTexture::SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
+                               bool useFenceSync, bool isControlledByApp)
+        : ConsumerBase(bq, isControlledByApp)
+        , mCurrentCrop(Rect::EMPTY_RECT)
+        , mCurrentTransform(0)
+        , mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE)
+        , mCurrentFence(Fence::NO_FENCE)
+        , mCurrentTimestamp(0)
+        , mCurrentDataSpace(HAL_DATASPACE_UNKNOWN)
+        , mCurrentFrameNumber(0)
+        , mDefaultWidth(1)
+        , mDefaultHeight(1)
+        , mFilteringEnabled(true)
+        , mTexName(0)
+        , mUseFenceSync(useFenceSync)
+        , mTexTarget(texTarget)
+        , mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT)
+        , mOpMode(OpMode::detached) {
+    SFT_LOGV("SurfaceTexture");
+
+    memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
+
+    mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+}
+
+status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h) {
+    Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("setDefaultBufferSize: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+    mDefaultWidth = w;
+    mDefaultHeight = h;
+    return mConsumer->setDefaultBufferSize(w, h);
+}
+
+status_t SurfaceTexture::updateTexImage() {
+    ATRACE_CALL();
+    SFT_LOGV("updateTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("updateTexImage: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+
+    return mEGLConsumer.updateTexImage(*this);
+}
+
+status_t SurfaceTexture::releaseTexImage() {
+    // releaseTexImage can be invoked even when not attached to a GL context.
+    ATRACE_CALL();
+    SFT_LOGV("releaseTexImage");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("releaseTexImage: SurfaceTexture is abandoned!");
+        return NO_INIT;
+    }
+
+    return mEGLConsumer.releaseTexImage(*this);
+}
+
+status_t SurfaceTexture::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
+                                             uint64_t maxFrameNumber) {
+    status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
+    if (err != NO_ERROR) {
+        return err;
+    }
+
+    switch (mOpMode) {
+        case OpMode::attachedToView:
+            mImageConsumer.onAcquireBufferLocked(item);
+            break;
+        case OpMode::attachedToGL:
+            mEGLConsumer.onAcquireBufferLocked(item, *this);
+            break;
+        case OpMode::detached:
+            break;
+    }
+
+    return NO_ERROR;
+}
+
+status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicBuffer,
+                                             EGLDisplay display, EGLSyncKHR eglFence) {
+    // release the buffer if it hasn't already been discarded by the
+    // BufferQueue. This can happen, for example, when the producer of this
+    // buffer has reallocated the original buffer slot after this buffer
+    // was acquired.
+    status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
+    // We could be releasing an EGL buffer, even if not currently attached to a GL context.
+    mImageConsumer.onReleaseBufferLocked(buf);
+    mEGLConsumer.onReleaseBufferLocked(buf);
+    return err;
+}
+
+status_t SurfaceTexture::detachFromContext() {
+    ATRACE_CALL();
+    SFT_LOGV("detachFromContext");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("detachFromContext: abandoned SurfaceTexture");
+        return NO_INIT;
+    }
+
+    if (mOpMode != OpMode::attachedToGL) {
+        SFT_LOGE("detachFromContext: SurfaceTexture is not attached to a GL context");
+        return INVALID_OPERATION;
+    }
+
+    status_t err = mEGLConsumer.detachFromContext(*this);
+    if (err == OK) {
+        mOpMode = OpMode::detached;
+    }
+
+    return err;
+}
+
+status_t SurfaceTexture::attachToContext(uint32_t tex) {
+    ATRACE_CALL();
+    SFT_LOGV("attachToContext");
+    Mutex::Autolock lock(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("attachToContext: abandoned SurfaceTexture");
+        return NO_INIT;
+    }
+
+    if (mOpMode != OpMode::detached) {
+        SFT_LOGE(
+                "attachToContext: SurfaceTexture is already attached to a "
+                "context");
+        return INVALID_OPERATION;
+    }
+
+    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        // release possible ImageConsumer cache
+        mImageConsumer.onFreeBufferLocked(mCurrentTexture);
+    }
+
+    return mEGLConsumer.attachToContext(tex, *this);
+}
+
+void SurfaceTexture::attachToView() {
+    ATRACE_CALL();
+    Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("attachToView: abandoned SurfaceTexture");
+        return;
+    }
+    if (mOpMode == OpMode::detached) {
+        mOpMode = OpMode::attachedToView;
+
+        if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+            // release possible EGLConsumer texture cache
+            mEGLConsumer.onFreeBufferLocked(mCurrentTexture);
+            mEGLConsumer.onAbandonLocked();
+        }
+    } else {
+        SFT_LOGE("attachToView: already attached");
+    }
+}
+
+void SurfaceTexture::detachFromView() {
+    ATRACE_CALL();
+    Mutex::Autolock _l(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("detachFromView: abandoned SurfaceTexture");
+        return;
+    }
+
+    if (mOpMode == OpMode::attachedToView) {
+        mOpMode = OpMode::detached;
+    } else {
+        SFT_LOGE("detachFromView: not attached to View");
+    }
+}
+
+uint32_t SurfaceTexture::getCurrentTextureTarget() const {
+    return mTexTarget;
+}
+
+void SurfaceTexture::getTransformMatrix(float mtx[16]) {
+    Mutex::Autolock lock(mMutex);
+    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+}
+
+void SurfaceTexture::setFilteringEnabled(bool enabled) {
+    Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        SFT_LOGE("setFilteringEnabled: SurfaceTexture is abandoned!");
+        return;
+    }
+    bool needsRecompute = mFilteringEnabled != enabled;
+    mFilteringEnabled = enabled;
+
+    if (needsRecompute && mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) {
+        SFT_LOGD("setFilteringEnabled called with no current item");
+    }
+
+    if (needsRecompute && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        computeCurrentTransformMatrixLocked();
+    }
+}
+
+void SurfaceTexture::computeCurrentTransformMatrixLocked() {
+    SFT_LOGV("computeCurrentTransformMatrixLocked");
+    sp<GraphicBuffer> buf = (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT)
+                                    ? nullptr
+                                    : mSlots[mCurrentTexture].mGraphicBuffer;
+    if (buf == nullptr) {
+        SFT_LOGD("computeCurrentTransformMatrixLocked: no current item");
+    }
+    computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop, mCurrentTransform,
+                           mFilteringEnabled);
+}
+
+void SurfaceTexture::computeTransformMatrix(float outTransform[16], const sp<GraphicBuffer>& buf,
+                                            const Rect& cropRect, uint32_t transform,
+                                            bool filtering) {
+    // Transform matrices
+    static const mat4 mtxFlipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+    static const mat4 mtxFlipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+    static const mat4 mtxRot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+
+    mat4 xform;
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+        xform *= mtxFlipH;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+        xform *= mtxFlipV;
+    }
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        xform *= mtxRot90;
+    }
+
+    if (!cropRect.isEmpty() && buf.get()) {
+        float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
+        float bufferWidth = buf->getWidth();
+        float bufferHeight = buf->getHeight();
+        float shrinkAmount = 0.0f;
+        if (filtering) {
+            // In order to prevent bilinear sampling beyond the edge of the
+            // crop rectangle we may need to shrink it by 2 texels in each
+            // dimension.  Normally this would just need to take 1/2 a texel
+            // off each end, but because the chroma channels of YUV420 images
+            // are subsampled we may need to shrink the crop region by a whole
+            // texel on each side.
+            switch (buf->getPixelFormat()) {
+                case PIXEL_FORMAT_RGBA_8888:
+                case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGBA_FP16:
+                case PIXEL_FORMAT_RGBA_1010102:
+                case PIXEL_FORMAT_RGB_888:
+                case PIXEL_FORMAT_RGB_565:
+                case PIXEL_FORMAT_BGRA_8888:
+                    // We know there's no subsampling of any channels, so we
+                    // only need to shrink by a half a pixel.
+                    shrinkAmount = 0.5;
+                    break;
+
+                default:
+                    // If we don't recognize the format, we must assume the
+                    // worst case (that we care about), which is YUV420.
+                    shrinkAmount = 1.0;
+                    break;
+            }
+        }
+
+        // Only shrink the dimensions that are not the size of the buffer.
+        if (cropRect.width() < bufferWidth) {
+            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) / bufferWidth;
+        }
+        if (cropRect.height() < bufferHeight) {
+            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) / bufferHeight;
+            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) / bufferHeight;
+        }
+
+        mat4 crop(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1);
+        xform = crop * xform;
+    }
+
+    // SurfaceFlinger expects the top of its window textures to be at a Y
+    // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
+    // want to expose this to applications, however, so we must add an
+    // additional vertical flip to the transform after all the other transforms.
+    xform = mtxFlipV * xform;
+
+    memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+Rect SurfaceTexture::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
+    Rect outCrop = crop;
+
+    uint32_t newWidth = static_cast<uint32_t>(crop.width());
+    uint32_t newHeight = static_cast<uint32_t>(crop.height());
+
+    if (newWidth * bufferHeight > newHeight * bufferWidth) {
+        newWidth = newHeight * bufferWidth / bufferHeight;
+        ALOGV("too wide: newWidth = %d", newWidth);
+    } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
+        newHeight = newWidth * bufferHeight / bufferWidth;
+        ALOGV("too tall: newHeight = %d", newHeight);
+    }
+
+    uint32_t currentWidth = static_cast<uint32_t>(crop.width());
+    uint32_t currentHeight = static_cast<uint32_t>(crop.height());
+
+    // The crop is too wide
+    if (newWidth < currentWidth) {
+        uint32_t dw = currentWidth - newWidth;
+        auto halfdw = dw / 2;
+        outCrop.left += halfdw;
+        // Not halfdw because it would subtract 1 too few when dw is odd
+        outCrop.right -= (dw - halfdw);
+        // The crop is too tall
+    } else if (newHeight < currentHeight) {
+        uint32_t dh = currentHeight - newHeight;
+        auto halfdh = dh / 2;
+        outCrop.top += halfdh;
+        // Not halfdh because it would subtract 1 too few when dh is odd
+        outCrop.bottom -= (dh - halfdh);
+    }
+
+    ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]", outCrop.left, outCrop.top, outCrop.right,
+          outCrop.bottom);
+
+    return outCrop;
+}
+
+nsecs_t SurfaceTexture::getTimestamp() {
+    SFT_LOGV("getTimestamp");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTimestamp;
+}
+
+android_dataspace SurfaceTexture::getCurrentDataSpace() {
+    SFT_LOGV("getCurrentDataSpace");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentDataSpace;
+}
+
+uint64_t SurfaceTexture::getFrameNumber() {
+    SFT_LOGV("getFrameNumber");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFrameNumber;
+}
+
+Rect SurfaceTexture::getCurrentCrop() const {
+    Mutex::Autolock lock(mMutex);
+    return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+                   ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+                   : mCurrentCrop;
+}
+
+uint32_t SurfaceTexture::getCurrentTransform() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentTransform;
+}
+
+uint32_t SurfaceTexture::getCurrentScalingMode() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentScalingMode;
+}
+
+sp<Fence> SurfaceTexture::getCurrentFence() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFence;
+}
+
+std::shared_ptr<FenceTime> SurfaceTexture::getCurrentFenceTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFenceTime;
+}
+
+void SurfaceTexture::freeBufferLocked(int slotIndex) {
+    SFT_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
+    if (slotIndex == mCurrentTexture) {
+        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
+    }
+    // The slotIndex buffer could have EGL or SkImage cache, but there is no way to tell for sure.
+    // Buffers can be freed after SurfaceTexture has detached from GL context or View.
+    mImageConsumer.onFreeBufferLocked(slotIndex);
+    mEGLConsumer.onFreeBufferLocked(slotIndex);
+    ConsumerBase::freeBufferLocked(slotIndex);
+}
+
+void SurfaceTexture::abandonLocked() {
+    SFT_LOGV("abandonLocked");
+    mEGLConsumer.onAbandonLocked();
+    ConsumerBase::abandonLocked();
+}
+
+status_t SurfaceTexture::setConsumerUsageBits(uint64_t usage) {
+    return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
+}
+
+void SurfaceTexture::dumpLocked(String8& result, const char* prefix) const {
+    result.appendFormat(
+            "%smTexName=%d mCurrentTexture=%d\n"
+            "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
+            prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left, mCurrentCrop.top,
+            mCurrentCrop.right, mCurrentCrop.bottom, mCurrentTransform);
+
+    ConsumerBase::dumpLocked(result, prefix);
+}
+
+sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
+                                            bool* queueEmpty,
+                                            uirenderer::RenderState& renderState) {
+    Mutex::Autolock _l(mMutex);
+
+    if (mAbandoned) {
+        SFT_LOGE("dequeueImage: SurfaceTexture is abandoned!");
+        return nullptr;
+    }
+
+    if (mOpMode != OpMode::attachedToView) {
+        SFT_LOGE("dequeueImage: SurfaceTexture is not attached to a View");
+        return nullptr;
+    }
+
+    auto image = mImageConsumer.dequeueImage(queueEmpty, *this, renderState);
+    if (image.get()) {
+        uirenderer::mat4(mCurrentTransformMatrix).copyTo(transformMatrix);
+        dataSpace = mCurrentDataSpace;
+    }
+    return image;
+}
+
+};  // namespace android
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.h b/libs/hwui/surfacetexture/SurfaceTexture.h
new file mode 100644
index 0000000..db392a9
--- /dev/null
+++ b/libs/hwui/surfacetexture/SurfaceTexture.h
@@ -0,0 +1,452 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <gui/BufferQueueDefs.h>
+#include <gui/ConsumerBase.h>
+
+#include <ui/FenceTime.h>
+#include <ui/GraphicBuffer.h>
+
+#include <utils/Mutex.h>
+#include <utils/String8.h>
+
+#include "EGLConsumer.h"
+#include "ImageConsumer.h"
+
+namespace android {
+
+namespace uirenderer {
+class RenderState;
+}
+
+/*
+ * SurfaceTexture consumes buffers of graphics data from a BufferQueue,
+ * and makes them available to HWUI render thread as a SkImage and to
+ * an application GL render thread as an OpenGL texture.
+ *
+ * When attached to an application GL render thread, a typical usage
+ * pattern is to set up the SurfaceTexture with the
+ * desired options, and call updateTexImage() when a new frame is desired.
+ * If a new frame is available, the texture will be updated.  If not,
+ * the previous contents are retained.
+ *
+ * When attached to a HWUI render thread, the TextureView implementation
+ * calls dequeueImage, which either pulls a new SkImage or returns the
+ * last cached SkImage if BufferQueue is empty.
+ * When attached to HWUI render thread, SurfaceTexture is compatible to
+ * both Vulkan and GL drawing pipelines.
+ */
+class ANDROID_API SurfaceTexture : public ConsumerBase {
+public:
+    enum { TEXTURE_EXTERNAL = 0x8D65 };  // GL_TEXTURE_EXTERNAL_OES
+    typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
+
+    /**
+     * SurfaceTexture constructs a new SurfaceTexture object. If the constructor with
+     * the tex parameter is used, tex indicates the name of the OpenGL ES
+     * texture to which images are to be streamed. texTarget specifies the
+     * OpenGL ES texture target to which the texture will be bound in
+     * updateTexImage. useFenceSync specifies whether fences should be used to
+     * synchronize access to buffers if that behavior is enabled at
+     * compile-time.
+     *
+     * A SurfaceTexture may be detached from one OpenGL ES context and then
+     * attached to a different context using the detachFromContext and
+     * attachToContext methods, respectively. The intention of these methods is
+     * purely to allow a SurfaceTexture to be transferred from one consumer
+     * context to another. If such a transfer is not needed there is no
+     * requirement that either of these methods be called.
+     *
+     * If the constructor with the tex parameter is used, the SurfaceTexture is
+     * created in a state where it is considered attached to an OpenGL ES
+     * context for the purposes of the attachToContext and detachFromContext
+     * methods. However, despite being considered "attached" to a context, the
+     * specific OpenGL ES context doesn't get latched until the first call to
+     * updateTexImage. After that point, all calls to updateTexImage must be
+     * made with the same OpenGL ES context current.
+     *
+     * If the constructor without the tex parameter is used, the SurfaceTexture is
+     * created in a detached state, and attachToContext must be called before
+     * calls to updateTexImage.
+     */
+    SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t tex, uint32_t texureTarget,
+                   bool useFenceSync, bool isControlledByApp);
+
+    SurfaceTexture(const sp<IGraphicBufferConsumer>& bq, uint32_t texureTarget, bool useFenceSync,
+                   bool isControlledByApp);
+
+    /**
+     * updateTexImage acquires the most recently queued buffer, and sets the
+     * image contents of the target texture to it.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     *
+     * This calls doGLFenceWait to ensure proper synchronization.
+     */
+    status_t updateTexImage();
+
+    /**
+     * releaseTexImage releases the texture acquired in updateTexImage().
+     * This is intended to be used in single buffer mode.
+     *
+     * This call may only be made while the OpenGL ES context to which the
+     * target texture belongs is bound to the calling thread.
+     */
+    status_t releaseTexImage();
+
+    /**
+     * getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
+     * associated with the texture image set by the most recent call to
+     * updateTexImage.
+     *
+     * This transform matrix maps 2D homogeneous texture coordinates of the form
+     * (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
+     * coordinate that should be used to sample that location from the texture.
+     * Sampling the texture outside of the range of this transform is undefined.
+     *
+     * This transform is necessary to compensate for transforms that the stream
+     * content producer may implicitly apply to the content. By forcing users of
+     * a SurfaceTexture to apply this transform we avoid performing an extra
+     * copy of the data that would be needed to hide the transform from the
+     * user.
+     *
+     * The matrix is stored in column-major order so that it may be passed
+     * directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
+     * functions.
+     */
+    void getTransformMatrix(float mtx[16]);
+
+    /**
+     * Computes the transform matrix documented by getTransformMatrix
+     * from the BufferItem sub parts.
+     */
+    static void computeTransformMatrix(float outTransform[16], const sp<GraphicBuffer>& buf,
+                                       const Rect& cropRect, uint32_t transform, bool filtering);
+
+    /**
+     * Scale the crop down horizontally or vertically such that it has the
+     * same aspect ratio as the buffer does.
+     */
+    static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight);
+
+    /**
+     * getTimestamp retrieves the timestamp associated with the texture image
+     * set by the most recent call to updateTexImage.
+     *
+     * The timestamp is in nanoseconds, and is monotonically increasing. Its
+     * other semantics (zero point, etc) are source-dependent and should be
+     * documented by the source.
+     */
+    int64_t getTimestamp();
+
+    /**
+     * getDataSpace retrieves the DataSpace associated with the texture image
+     * set by the most recent call to updateTexImage.
+     */
+    android_dataspace getCurrentDataSpace();
+
+    /**
+     * getFrameNumber retrieves the frame number associated with the texture
+     * image set by the most recent call to updateTexImage.
+     *
+     * The frame number is an incrementing counter set to 0 at the creation of
+     * the BufferQueue associated with this consumer.
+     */
+    uint64_t getFrameNumber();
+
+    /**
+     * setDefaultBufferSize is used to set the size of buffers returned by
+     * requestBuffers when a with and height of zero is requested.
+     * A call to setDefaultBufferSize() may trigger requestBuffers() to
+     * be called from the client.
+     * The width and height parameters must be no greater than the minimum of
+     * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
+     * An error due to invalid dimensions might not be reported until
+     * updateTexImage() is called.
+     */
+    status_t setDefaultBufferSize(uint32_t width, uint32_t height);
+
+    /**
+     * setFilteringEnabled sets whether the transform matrix should be computed
+     * for use with bilinear filtering.
+     */
+    void setFilteringEnabled(bool enabled);
+
+    /**
+     * getCurrentTextureTarget returns the texture target of the current
+     * texture as returned by updateTexImage().
+     */
+    uint32_t getCurrentTextureTarget() const;
+
+    /**
+     * getCurrentCrop returns the cropping rectangle of the current buffer.
+     */
+    Rect getCurrentCrop() const;
+
+    /**
+     * getCurrentTransform returns the transform of the current buffer.
+     */
+    uint32_t getCurrentTransform() const;
+
+    /**
+     * getCurrentScalingMode returns the scaling mode of the current buffer.
+     */
+    uint32_t getCurrentScalingMode() const;
+
+    /**
+     * getCurrentFence returns the fence indicating when the current buffer is
+     * ready to be read from.
+     */
+    sp<Fence> getCurrentFence() const;
+
+    /**
+     * getCurrentFence returns the FenceTime indicating when the current
+     * buffer is ready to be read from.
+     */
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const;
+
+    /**
+     * setConsumerUsageBits overrides the ConsumerBase method to OR
+     * DEFAULT_USAGE_FLAGS to usage.
+     */
+    status_t setConsumerUsageBits(uint64_t usage);
+
+    /**
+     * detachFromContext detaches the SurfaceTexture from the calling thread's
+     * current OpenGL ES context.  This context must be the same as the context
+     * that was current for previous calls to updateTexImage.
+     *
+     * Detaching a SurfaceTexture from an OpenGL ES context will result in the
+     * deletion of the OpenGL ES texture object into which the images were being
+     * streamed.  After a SurfaceTexture has been detached from the OpenGL ES
+     * context calls to updateTexImage will fail returning INVALID_OPERATION
+     * until the SurfaceTexture is attached to a new OpenGL ES context using the
+     * attachToContext method.
+     */
+    status_t detachFromContext();
+
+    /**
+     * attachToContext attaches a SurfaceTexture that is currently in the
+     * 'detached' state to the current OpenGL ES context.  A SurfaceTexture is
+     * in the 'detached' state iff detachFromContext has successfully been
+     * called and no calls to attachToContext have succeeded since the last
+     * detachFromContext call.  Calls to attachToContext made on a
+     * SurfaceTexture that is not in the 'detached' state will result in an
+     * INVALID_OPERATION error.
+     *
+     * The tex argument specifies the OpenGL ES texture object name in the
+     * new context into which the image contents will be streamed.  A successful
+     * call to attachToContext will result in this texture object being bound to
+     * the texture target and populated with the image contents that were
+     * current at the time of the last call to detachFromContext.
+     */
+    status_t attachToContext(uint32_t tex);
+
+    sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
+                                bool* queueEmpty, uirenderer::RenderState& renderState);
+
+    /**
+     * attachToView attaches a SurfaceTexture that is currently in the
+     * 'detached' state to HWUI View system.
+     */
+    void attachToView();
+
+    /**
+     * detachFromView detaches a SurfaceTexture from HWUI View system.
+     */
+    void detachFromView();
+
+protected:
+    /**
+     * abandonLocked overrides the ConsumerBase method to clear
+     * mCurrentTextureImage in addition to the ConsumerBase behavior.
+     */
+    virtual void abandonLocked();
+
+    /**
+     * dumpLocked overrides the ConsumerBase method to dump SurfaceTexture-
+     * specific info in addition to the ConsumerBase behavior.
+     */
+    virtual void dumpLocked(String8& result, const char* prefix) const override;
+
+    /**
+     * acquireBufferLocked overrides the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase behavior.
+     */
+    virtual status_t acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
+                                         uint64_t maxFrameNumber = 0) override;
+
+    /**
+     * releaseBufferLocked overrides the ConsumerBase method to update the
+     * mEglSlots array in addition to the ConsumerBase.
+     */
+    virtual status_t releaseBufferLocked(int slot, const sp<GraphicBuffer> graphicBuffer,
+                                         EGLDisplay display, EGLSyncKHR eglFence) override;
+
+    /**
+     * freeBufferLocked frees up the given buffer slot. If the slot has been
+     * initialized this will release the reference to the GraphicBuffer in that
+     * slot and destroy the EGLImage in that slot.  Otherwise it has no effect.
+     *
+     * This method must be called with mMutex locked.
+     */
+    virtual void freeBufferLocked(int slotIndex);
+
+    /**
+     * computeCurrentTransformMatrixLocked computes the transform matrix for the
+     * current texture.  It uses mCurrentTransform and the current GraphicBuffer
+     * to compute this matrix and stores it in mCurrentTransformMatrix.
+     * mCurrentTextureImage must not be NULL.
+     */
+    void computeCurrentTransformMatrixLocked();
+
+    /**
+     * The default consumer usage flags that SurfaceTexture always sets on its
+     * BufferQueue instance; these will be OR:d with any additional flags passed
+     * from the SurfaceTexture user. In particular, SurfaceTexture will always
+     * consume buffers as hardware textures.
+     */
+    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
+
+    /**
+     * mCurrentCrop is the crop rectangle that applies to the current texture.
+     * It gets set each time updateTexImage is called.
+     */
+    Rect mCurrentCrop;
+
+    /**
+     * mCurrentTransform is the transform identifier for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    uint32_t mCurrentTransform;
+
+    /**
+     * mCurrentScalingMode is the scaling mode for the current texture. It gets
+     * set each time updateTexImage is called.
+     */
+    uint32_t mCurrentScalingMode;
+
+    /**
+     * mCurrentFence is the fence received from BufferQueue in updateTexImage.
+     */
+    sp<Fence> mCurrentFence;
+
+    /**
+     * The FenceTime wrapper around mCurrentFence.
+     */
+    std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
+
+    /**
+     * mCurrentTransformMatrix is the transform matrix for the current texture.
+     * It gets computed by computeTransformMatrix each time updateTexImage is
+     * called.
+     */
+    float mCurrentTransformMatrix[16];
+
+    /**
+     * mCurrentTimestamp is the timestamp for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    int64_t mCurrentTimestamp;
+
+    /**
+     * mCurrentDataSpace is the dataspace for the current texture. It
+     * gets set each time updateTexImage is called.
+     */
+    android_dataspace mCurrentDataSpace;
+
+    /**
+     * mCurrentFrameNumber is the frame counter for the current texture.
+     * It gets set each time updateTexImage is called.
+     */
+    uint64_t mCurrentFrameNumber;
+
+    uint32_t mDefaultWidth, mDefaultHeight;
+
+    /**
+     * mFilteringEnabled indicates whether the transform matrix is computed for
+     * use with bilinear filtering. It defaults to true and is changed by
+     * setFilteringEnabled().
+     */
+    bool mFilteringEnabled;
+
+    /**
+     * mTexName is the name of the OpenGL texture to which streamed images will
+     * be bound when updateTexImage is called. It is set at construction time
+     * and can be changed with a call to attachToContext.
+     */
+    uint32_t mTexName;
+
+    /**
+     * mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
+     * extension should be used to prevent buffers from being dequeued before
+     * it's safe for them to be written. It gets set at construction time and
+     * never changes.
+     */
+    const bool mUseFenceSync;
+
+    /**
+     * mTexTarget is the GL texture target with which the GL texture object is
+     * associated.  It is set in the constructor and never changed.  It is
+     * almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
+     * Browser.  In that case it is set to GL_TEXTURE_2D to allow
+     * glCopyTexSubImage to read from the texture.  This is a hack to work
+     * around a GL driver limitation on the number of FBO attachments, which the
+     * browser's tile cache exceeds.
+     */
+    const uint32_t mTexTarget;
+
+    /**
+     * mCurrentTexture is the buffer slot index of the buffer that is currently
+     * bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
+     * indicating that no buffer slot is currently bound to the texture. Note,
+     * however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+     * that no buffer is bound to the texture. A call to setBufferCount will
+     * reset mCurrentTexture to INVALID_BUFFER_SLOT.
+     */
+    int mCurrentTexture;
+
+    enum class OpMode { detached, attachedToView, attachedToGL };
+    /**
+     * mOpMode indicates whether the SurfaceTexture is currently attached to
+     * an OpenGL ES context or the HWUI view system.  For legacy reasons, this is initialized to,
+     * "attachedToGL" indicating that the SurfaceTexture is considered to be attached to
+     * whatever GL context is current at the time of the first updateTexImage call.
+     * It is set to "detached" by detachFromContext, and then set to "attachedToGL" again by
+     * attachToContext.
+     * attachToView/detachFromView are used to attach/detach from HWUI view system.
+     */
+    OpMode mOpMode;
+
+    /**
+     * mEGLConsumer has SurfaceTexture logic used when attached to GL context.
+     */
+    EGLConsumer mEGLConsumer;
+
+    /**
+     * mImageConsumer has SurfaceTexture logic used when attached to HWUI view system.
+     */
+    ImageConsumer mImageConsumer;
+
+    friend class ImageConsumer;
+    friend class EGLConsumer;
+};
+
+// ----------------------------------------------------------------------------
+};  // namespace android
diff --git a/libs/hwui/tests/common/LeakChecker.cpp b/libs/hwui/tests/common/LeakChecker.cpp
index 5b36154..d2d37dc 100644
--- a/libs/hwui/tests/common/LeakChecker.cpp
+++ b/libs/hwui/tests/common/LeakChecker.cpp
@@ -16,7 +16,6 @@
 
 #include "LeakChecker.h"
 
-#include "Caches.h"
 #include "TestUtils.h"
 
 #include <memunreachable/memunreachable.h>
@@ -71,9 +70,6 @@
     // thread-local caches so some leaks will not be properly tagged as leaks
     UnreachableMemoryInfo rtMemInfo;
     TestUtils::runOnRenderThread([&rtMemInfo](renderthread::RenderThread& thread) {
-        if (Caches::hasInstance()) {
-            Caches::getInstance().tasks.stop();
-        }
         // Check for leaks
         if (!GetUnreachableMemory(rtMemInfo)) {
             cerr << "Failed to get unreachable memory!" << endl;
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 6958634..66b9b85 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -67,16 +67,14 @@
         renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
         const SkMatrix& transform) {
     sp<DeferredLayerUpdater> layerUpdater = createTextureLayerUpdater(renderThread);
-    layerUpdater->backingLayer()->getTransform().load(transform);
+    layerUpdater->backingLayer()->getTransform() = transform;
     layerUpdater->setSize(width, height);
     layerUpdater->setTransform(&transform);
 
     // updateLayer so it's ready to draw
-    layerUpdater->updateLayer(true, Matrix4::identity().data, HAL_DATASPACE_UNKNOWN);
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        static_cast<GlLayer*>(layerUpdater->backingLayer())
-                ->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
-    }
+    SkMatrix identity;
+    identity.setIdentity();
+    layerUpdater->updateLayer(true, identity, HAL_DATASPACE_UNKNOWN, nullptr);
     return layerUpdater;
 }
 
@@ -117,7 +115,6 @@
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
         renderThread.vulkanManager().destroy();
     } else {
-        renderThread.renderState().flush(Caches::FlushMode::Full);
         renderThread.destroyGlContext();
     }
 }
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 743f809..0e6582c 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -18,7 +18,6 @@
 
 #include <DeviceInfo.h>
 #include <DisplayList.h>
-#include <GlLayer.h>
 #include <Matrix.h>
 #include <Properties.h>
 #include <Rect.h>
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index f29830f..6c8775b 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -15,12 +15,13 @@
  */
 
 #include "DeferredLayerUpdater.h"
-#include "GlLayer.h"
 #include "Properties.h"
 
 #include "tests/common/TestUtils.h"
 
 #include <gtest/gtest.h>
+#include <SkBitmap.h>
+#include <SkImage.h>
 
 using namespace android;
 using namespace android::uirenderer;
@@ -31,10 +32,6 @@
     layerUpdater->setBlend(true);
 
     // updates are deferred so the backing layer should still be in its default state
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        EXPECT_EQ((uint32_t)GL_NONE, glLayer->getRenderTarget());
-    }
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(0u, layerUpdater->backingLayer()->getHeight());
     EXPECT_FALSE(layerUpdater->backingLayer()->getForceFilter());
@@ -42,19 +39,13 @@
     EXPECT_EQ(Matrix4::identity(), layerUpdater->backingLayer()->getTexTransform());
 
     // push the deferred updates to the layer
-    Matrix4 scaledMatrix;
-    scaledMatrix.loadScale(0.5, 0.5, 0.0);
-    layerUpdater->updateLayer(true, scaledMatrix.data, HAL_DATASPACE_UNKNOWN);
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        glLayer->setRenderTarget(GL_TEXTURE_EXTERNAL_OES);
-    }
+    SkMatrix scaledMatrix = SkMatrix::MakeScale(0.5, 0.5);
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(16, 16);
+    sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
+    layerUpdater->updateLayer(true, scaledMatrix, HAL_DATASPACE_UNKNOWN, layerImage);
 
     // the backing layer should now have all the properties applied.
-    if (layerUpdater->backingLayer()->getApi() == Layer::Api::OpenGL) {
-        GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
-        EXPECT_EQ((uint32_t)GL_TEXTURE_EXTERNAL_OES, glLayer->getRenderTarget());
-    }
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
     EXPECT_EQ(100u, layerUpdater->backingLayer()->getHeight());
     EXPECT_TRUE(layerUpdater->backingLayer()->getForceFilter());
diff --git a/libs/hwui/tests/unit/FatalTestCanvas.h b/libs/hwui/tests/unit/FatalTestCanvas.h
index 9693ce7..89f0c52 100644
--- a/libs/hwui/tests/unit/FatalTestCanvas.h
+++ b/libs/hwui/tests/unit/FatalTestCanvas.h
@@ -42,10 +42,6 @@
                         const SkPaint& paint) {
         ADD_FAILURE() << "onDrawPosTextH not expected in this test";
     }
-    void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
-                          const SkMatrix* matrix, const SkPaint& paint) {
-        ADD_FAILURE() << "onDrawTextOnPath not expected in this test";
-    }
     void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
                            const SkRect* cullRect, const SkPaint& paint) {
         ADD_FAILURE() << "onDrawTextRSXform not expected in this test";
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 9e6d9a8..aecceb3 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -17,12 +17,13 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
-#include "Caches.h"
 #include "debug/GlesDriver.h"
 #include "debug/NullGlesDriver.h"
 #include "hwui/Typeface.h"
 #include "Properties.h"
 #include "tests/common/LeakChecker.h"
+#include "thread/TaskProcessor.h"
+#include "thread/Task.h"
 #include "thread/TaskManager.h"
 
 #include <signal.h>
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index f8e8a0a..ebf2343 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -16,6 +16,7 @@
 #ifndef PAINT_UTILS_H
 #define PAINT_UTILS_H
 
+#include <GLES2/gl2.h>
 #include <utils/Blur.h>
 
 #include <SkColorFilter.h>
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 4fb5e74..43847cc 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -64,6 +64,7 @@
         "libsensor",
         "libandroid_runtime",
         "libnetd_client",
+        "libhwui",
     ],
 
     static_libs: [
diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp
index b266881..ced279277 100644
--- a/native/android/surface_texture.cpp
+++ b/native/android/surface_texture.cpp
@@ -21,15 +21,16 @@
 
 #include <utils/Log.h>
 
-#include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 
+#include "surfacetexture/SurfaceTexture.h"
+
 using namespace android;
 
 struct ASurfaceTexture {
-    sp<GLConsumer> consumer;
+    sp<SurfaceTexture> consumer;
     sp<IGraphicBufferProducer> producer;
 };
 
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 9f89d3c..149de13 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -33,7 +33,6 @@
 import android.net.Proxy;
 import android.net.Uri;
 import android.net.captiveportal.CaptivePortalProbeSpec;
-import android.net.dns.ResolvUtil;
 import android.net.http.SslError;
 import android.net.wifi.WifiInfo;
 import android.os.Build;
@@ -132,9 +131,9 @@
         }
 
         // Also initializes proxy system properties.
+        mNetwork = mNetwork.getPrivateDnsBypassingCopy();
         mCm.bindProcessToNetwork(mNetwork);
-        mCm.setProcessDefaultNetworkForHostResolution(
-                ResolvUtil.getNetworkWithUseLocalNameserversFlag(mNetwork));
+        mCm.setProcessDefaultNetworkForHostResolution(mNetwork);
 
         // Proxy system properties must be initialized before setContentView is called because
         // setContentView initializes the WebView logic which in turn reads the system properties.
@@ -334,7 +333,6 @@
         // TODO: reuse NetworkMonitor facilities for consistent captive portal detection.
         new Thread(new Runnable() {
             public void run() {
-                final Network network = ResolvUtil.makeNetworkWithPrivateDnsBypass(mNetwork);
                 // Give time for captive portal to open.
                 try {
                     Thread.sleep(1000);
@@ -344,7 +342,7 @@
                 int httpResponseCode = 500;
                 String locationHeader = null;
                 try {
-                    urlConnection = (HttpURLConnection) network.openConnection(mUrl);
+                    urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
                     urlConnection.setInstanceFollowRedirects(false);
                     urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
                     urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index a7217ec..ff70e97 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -55,6 +55,12 @@
             <intent-filter>
                 <action android:name="android.service.autofill.AutofillFieldClassificationService" />
             </intent-filter>
+            <meta-data
+                android:name="android.autofill.field_classification.default_algorithm"
+                android:resource="@string/autofill_field_classification_default_algorithm" />
+            <meta-data
+                android:name="android.autofill.field_classification.available_algorithms"
+                android:resource="@array/autofill_field_classification_available_algorithms" />
         </service>
 
         <library android:name="android.ext.services"/>
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
index cf1c2c3..3bade25 100644
--- a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
@@ -20,11 +20,12 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import androidx.preference.PreferenceDialogFragment;
-import androidx.preference.DialogPreference;
 import android.util.AttributeSet;
 import android.view.View;
 
+import androidx.preference.DialogPreference;
+import androidx.preference.PreferenceDialogFragment;
+
 public class CustomDialogPreference extends DialogPreference {
 
     private CustomPreferenceDialogFragment mFragment;
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
index 04c3954..dfaff61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
@@ -23,13 +23,14 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import androidx.annotation.CallSuper;
-import androidx.preference.EditTextPreferenceDialogFragment;
-import androidx.preference.EditTextPreference;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.EditText;
 
+import androidx.annotation.CallSuper;
+import androidx.preference.EditTextPreference;
+import androidx.preference.EditTextPreferenceDialogFragment;
+
 public class CustomEditTextPreference extends EditTextPreference {
 
     private CustomPreferenceDialogFragment mFragment;
diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
index c98bc39..bc5a2c0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib;
 
+import static android.content.Context.TELEPHONY_SERVICE;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -30,6 +32,7 @@
 import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.util.Log;
+
 import androidx.annotation.VisibleForTesting;
 
 import java.io.BufferedReader;
@@ -43,8 +46,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import static android.content.Context.TELEPHONY_SERVICE;
-
 public class DeviceInfoUtils {
     private static final String TAG = "DeviceInfoUtils";
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
index 8055caa..4cbeb8a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -24,16 +24,15 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.net.Uri;
 import android.provider.Settings.Global;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MenuItem.OnMenuItemClickListener;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 7f518c1..bd54edd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -35,7 +35,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
@@ -43,6 +42,8 @@
 import android.view.MenuItem;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.widget.LockPatternUtils;
 
 import java.util.List;
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index 79e011c..ad7e995 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -16,15 +16,16 @@
 
 package com.android.settingslib;
 
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
 import android.content.Context;
 import android.os.UserHandle;
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
 import android.view.View;
 
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceViewHolder;
 
 /**
  * Preference class that supports being disabled by a user restriction
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index a930bb8..4b84920 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -16,19 +16,18 @@
 
 package com.android.settingslib;
 
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
-import android.view.View;
 import android.widget.TextView;
 
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
 
 /**
  * Helper class for managing settings preferences that can be disabled
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index fe6d9fe..0ed507c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -21,15 +21,16 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.UserHandle;
-import androidx.preference.SwitchPreference;
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.TextView;
 
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
 /**
  * Version of SwitchPreference that can be disabled by a device admin
  * using a user restriction.
diff --git a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
index b8516dc..a3ab4fd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TetherUtil.java
@@ -22,6 +22,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.telephony.CarrierConfigManager;
+
 import androidx.annotation.VisibleForTesting;
 
 public class TetherUtil {
diff --git a/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java b/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
index 3a26f46..02895a4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/TwoTargetPreference.java
@@ -18,13 +18,14 @@
 
 import android.annotation.IntDef;
 import android.content.Context;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java
index df76125..efac6bc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/animation/AppearAnimationUtils.java
@@ -19,15 +19,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.view.RenderNodeAnimator;
 import android.view.View;
-import android.view.ViewPropertyAnimator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
-import com.android.internal.widget.LockPatternView;
 import com.android.settingslib.R;
 
 /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 21bac88..663b1f5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -51,6 +51,11 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 
@@ -71,11 +76,6 @@
 import java.util.UUID;
 import java.util.regex.Pattern;
 
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.OnLifecycleEvent;
-
 /**
  * Keeps track of information about all installed applications, lazy-loading
  * as needed.
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index b15f35d..b457406 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
+
 import androidx.annotation.VisibleForTesting;
 
 import java.io.IOException;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 10fd683..e071b7c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -18,7 +18,6 @@
 
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHearingAid;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index d837975..ee80aa1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -5,9 +5,10 @@
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.DrawableRes;
 import android.util.Pair;
 
+import androidx.annotation.DrawableRes;
+
 import com.android.settingslib.R;
 import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 68e1dfc..649900b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.bluetooth;
 
+import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
@@ -27,7 +28,7 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
-import android.bluetooth.BluetoothAdapter;
+
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 47bd853..5a64e02 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -31,8 +31,8 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 6eaa620..1eeb4f0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -16,10 +16,10 @@
 
 package com.android.settingslib.bluetooth;
 
-import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.util.Log;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 4b4db75..f9f6233 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -16,10 +16,10 @@
 
 package com.android.settingslib.bluetooth;
 
-import android.bluetooth.BluetoothHeadsetClient;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
index 1c50953..51601a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
@@ -75,6 +75,8 @@
                 mCachedDeviceManager, context);
         mProfileManager = new LocalBluetoothProfileManager(context,
                 mLocalAdapter, mCachedDeviceManager, mEventManager);
+
+        mProfileManager.updateLocalProfiles();
         mEventManager.readPairedDevices();
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 8bb8210..36d209e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -35,8 +35,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.ParcelUuid;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.R;
 import com.android.internal.util.CollectionUtils;
 
@@ -119,7 +121,6 @@
         // pass this reference to adapter and event manager (circular dependency)
         adapter.setProfileManager(this);
 
-        updateLocalProfiles();
         if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
index e5c0b14..dfd1622 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -16,12 +16,12 @@
 
 package com.android.settingslib.bluetooth;
 
-import com.android.settingslib.R;
-
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 
+import com.android.settingslib.R;
+
 /**
  * OppProfile handles Bluetooth OPP.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index ad3506f..b295f24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -16,10 +16,10 @@
 
 package com.android.settingslib.bluetooth;
 
-import android.bluetooth.BluetoothPbapClient;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPbapClient;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index f0e259e..61602c6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -19,8 +19,8 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothSap;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothSap;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
 import android.os.ParcelUuid;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
index f4d647d..9572fb3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
@@ -1,6 +1,7 @@
 package com.android.settingslib.core;
 
 import android.content.Context;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
index 7227304..78963f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.metrics.LogMaker;
-import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.logging.MetricsLogger;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index a79f125..a28e45c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -20,11 +20,12 @@
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.os.AsyncTask;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.util.Map;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
index cb1ca59d..06d7c4d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
@@ -16,17 +16,18 @@
 
 package com.android.settingslib.core.instrumentation;
 
+import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
+
 import android.app.Activity;
+import android.content.Intent;
+import android.os.SystemClock;
+
 import androidx.lifecycle.Lifecycle.Event;
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
-import android.content.Intent;
 
-import android.os.SystemClock;
 import com.android.internal.logging.nano.MetricsProto;
 
-import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
-
 /**
  * Logs visibility change of a fragment.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/Lifecycle.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/Lifecycle.java
index 7ec757a..56de280 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/Lifecycle.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/Lifecycle.java
@@ -18,19 +18,20 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_ANY;
 
 import android.annotation.UiThread;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.lifecycle.OnLifecycleEvent;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.preference.PreferenceScreen;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.core.lifecycle.events.OnAttach;
 import com.android.settingslib.core.lifecycle.events.OnCreate;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnCreate.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnCreate.java
index ada1537..ae67411 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnCreate.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnCreate.java
@@ -16,12 +16,10 @@
 package com.android.settingslib.core.lifecycle.events;
 
 
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.OnLifecycleEvent;
 import android.os.Bundle;
 
 /**
- * @deprecated use {@link OnLifecycleEvent(Lifecycle.Event) }
+ * @deprecated use {@link androidx.lifecycle.OnLifecycleEvent}
  */
 @Deprecated
 public interface OnCreate {
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnPrepareOptionsMenu.java b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnPrepareOptionsMenu.java
index b9f1371..92ae9fd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnPrepareOptionsMenu.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/lifecycle/events/OnPrepareOptionsMenu.java
@@ -17,7 +17,6 @@
 package com.android.settingslib.core.lifecycle.events;
 
 import android.view.Menu;
-import android.view.MenuInflater;
 
 public interface OnPrepareOptionsMenu {
     void onPrepareOptionsMenu(Menu menu);
diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
index 75c2533..8fac3fd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
@@ -20,9 +20,6 @@
 import android.content.res.XmlResourceParser;
 import android.icu.text.TimeZoneFormat;
 import android.icu.text.TimeZoneNames;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.text.BidiFormatter;
-import androidx.core.text.TextDirectionHeuristicsCompat;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -31,6 +28,10 @@
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.core.text.BidiFormatter;
+import androidx.core.text.TextDirectionHeuristicsCompat;
+
 import com.android.settingslib.R;
 
 import libcore.util.TimeZoneFinder;
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java
index b512448..caabf9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/AbstractEnableAdbPreferenceController.java
@@ -22,13 +22,14 @@
 import android.content.Intent;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.text.TextUtils;
+
 import androidx.annotation.VisibleForTesting;
-import androidx.preference.SwitchPreference;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
 import androidx.preference.TwoStatePreference;
-import android.text.TextUtils;
 
 import com.android.settingslib.core.ConfirmationDialogController;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogdSizePreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogdSizePreferenceController.java
index e2f6b7b..5a82397 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogdSizePreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogdSizePreferenceController.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.SystemProperties;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import androidx.preference.ListPreference;
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogpersistPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogpersistPreferenceController.java
index f277c16..8722674 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogpersistPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/AbstractLogpersistPreferenceController.java
@@ -22,12 +22,13 @@
 import android.content.IntentFilter;
 import android.os.Bundle;
 import android.os.SystemProperties;
+import android.text.TextUtils;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.TextUtils;
 
 import com.android.settingslib.R;
 import com.android.settingslib.core.ConfirmationDialogController;
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/DeveloperOptionsPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/development/DeveloperOptionsPreferenceController.java
index 15d5522..f757aa4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/DeveloperOptionsPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/DeveloperOptionsPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.development;
 
 import android.content.Context;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
index 13d28fc..b191f88 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/DevelopmentSettingsEnabler.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.UserManager;
 import android.provider.Settings;
+
 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
 
 public class DevelopmentSettingsEnabler {
diff --git a/packages/SettingsLib/src/com/android/settingslib/development/SystemPropPoker.java b/packages/SettingsLib/src/com/android/settingslib/development/SystemPropPoker.java
index dba22d0..3f16be1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/development/SystemPropPoker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/development/SystemPropPoker.java
@@ -21,9 +21,10 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.util.Log;
+
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
-import android.util.Log;
 
 public class SystemPropPoker  {
     private static final String TAG = "SystemPropPoker";
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBluetoothAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBluetoothAddressPreferenceController.java
index 821b4d5..7455912 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBluetoothAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractBluetoothAddressPreferenceController.java
@@ -19,10 +19,11 @@
 import android.annotation.SuppressLint;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
+import android.text.TextUtils;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.TextUtils;
 
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
index 10260de..a5f4036 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractImsStatusPreferenceController.java
@@ -21,13 +21,14 @@
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.PersistableBundle;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
index 45cd866..24da72e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractIpAddressPreferenceController.java
@@ -20,6 +20,7 @@
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
 import android.net.wifi.WifiManager;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractSerialNumberPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractSerialNumberPreferenceController.java
index 60b29fb..d28792e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractSerialNumberPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractSerialNumberPreferenceController.java
@@ -18,10 +18,11 @@
 
 import android.content.Context;
 import android.os.Build;
+import android.text.TextUtils;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.TextUtils;
 
 import com.android.settingslib.core.AbstractPreferenceController;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
index ba93970..5f72269 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractUptimePreferenceController.java
@@ -20,10 +20,11 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
+import android.text.format.DateUtils;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.format.DateUtils;
 
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
index ffbda3a..9699294 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractWifiMacAddressPreferenceController.java
@@ -22,10 +22,11 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.provider.Settings;
+import android.text.TextUtils;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.TextUtils;
 
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
index af8fd4c..e0ca1ab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
@@ -16,11 +16,8 @@
 
 package com.android.settingslib.display;
 
-import com.android.settingslib.R;
-
 import android.content.Context;
 import android.content.res.Resources;
-import android.hardware.display.DisplayManager;
 import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -31,6 +28,8 @@
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
 
+import com.android.settingslib.R;
+
 import java.util.Arrays;
 
 /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index 94efc71..9feacac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -28,11 +28,11 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.ArrayUtils;
 
-import androidx.annotation.VisibleForTesting;
-
 /**
  * Handles getting/changing the whitelist for the exceptions to battery saving features.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
index d0804bb..f01eb2a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
@@ -19,18 +19,13 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
-import androidx.annotation.VisibleForTesting;
 import android.view.Gravity;
-import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java
index 628e70a..117b48f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManager.java
@@ -19,16 +19,17 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
 import android.text.TextUtils;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
 import com.android.settingslib.R;
 
 import java.text.Collator;
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
index ad1368c..6f8c7ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeEnablerManagerCompat.java
@@ -24,6 +24,12 @@
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
 import com.android.settingslib.R;
 
 import java.text.Collator;
@@ -31,12 +37,6 @@
 import java.util.HashMap;
 import java.util.List;
 
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
-
 public class InputMethodAndSubtypeEnablerManagerCompat implements
         Preference.OnPreferenceChangeListener {
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java
index 026bbd4..057123b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtil.java
@@ -25,15 +25,16 @@
 import android.icu.text.ListFormatter;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
 import com.android.internal.app.LocaleHelper;
 
 import java.util.HashMap;
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
index 9ad2adb..692dfbf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompat.java
@@ -30,6 +30,11 @@
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
 import com.android.internal.app.LocaleHelper;
 
 import java.util.HashMap;
@@ -38,11 +43,6 @@
 import java.util.Locale;
 import java.util.Map;
 
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
-
 // TODO: Consolidate this with {@link InputMethodSettingValuesWrapper}.
 public class InputMethodAndSubtypeUtilCompat {
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
index 2dec6c3..221e0dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -24,9 +24,6 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.UserHandle;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
-import androidx.preference.Preference.OnPreferenceClickListener;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.inputmethod.InputMethodInfo;
@@ -34,6 +31,10 @@
 import android.view.inputmethod.InputMethodSubtype;
 import android.widget.Toast;
 
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.Preference.OnPreferenceClickListener;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.R;
 import com.android.settingslib.RestrictedLockUtils;
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java
index bb43581..69bfffb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodSubtypePreference.java
@@ -17,11 +17,12 @@
 package com.android.settingslib.inputmethod;
 
 import android.content.Context;
-import androidx.preference.Preference;
 import android.text.TextUtils;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
 
+import androidx.preference.Preference;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.text.Collator;
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java
index 2b38697..2360298 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/SwitchWithNoTextPreference.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.inputmethod;
 
 import android.content.Context;
+
 import androidx.preference.SwitchPreference;
 
 public class SwitchWithNoTextPreference extends SwitchPreference {
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index 444c19c..42306f6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -16,11 +16,12 @@
 
 package com.android.settingslib.license;
 
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Xml;
 
+import androidx.annotation.VisibleForTesting;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
index d3b1903..360c19c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
@@ -36,7 +36,8 @@
             "/vendor/etc/NOTICE.xml.gz",
             "/odm/etc/NOTICE.xml.gz",
             "/oem/etc/NOTICE.xml.gz",
-            "/product/etc/NOTICE.xml.gz"};
+            "/product/etc/NOTICE.xml.gz",
+            "/product_services/etc/NOTICE.xml.gz"};
     static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
 
     private final Context mContext;
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 96bed93..b8e1251 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -25,10 +25,12 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-import androidx.annotation.VisibleForTesting;
 import android.text.format.DateUtils;
 import android.util.IconDrawableFactory;
 import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
index 3adbd4d..c3241bb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoaderCompat.java
@@ -30,10 +30,10 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
-import com.android.settingslib.AppItem;
-
 import androidx.loader.content.AsyncTaskLoader;
 
+import com.android.settingslib.AppItem;
+
 /**
  * Loader for historical chart data for both network and UID details.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index 224b967..c14f558 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -28,9 +28,9 @@
 import android.graphics.drawable.Drawable;
 import android.net.ConnectivityManager;
 import android.net.TrafficStats;
-import android.os.UserManager;
-import android.os.UserHandle;
 import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 0ef46a1..b9197fe 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -33,6 +33,9 @@
 import android.widget.ScrollView;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.policy.PhoneWindow;
@@ -40,9 +43,6 @@
 
 import java.util.Arrays;
 
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-
 public class ZenDurationDialog {
     private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
     @VisibleForTesting protected static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
index 6a8b01a..ec77487 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionController.java
@@ -24,9 +24,10 @@
 import android.os.RemoteException;
 import android.service.settings.suggestions.ISuggestionService;
 import android.service.settings.suggestions.Suggestion;
+import android.util.Log;
+
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
-import android.util.Log;
 
 import java.util.List;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
index ee8b6fe..6597daa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixin.java
@@ -17,15 +17,16 @@
 package com.android.settingslib.suggestions;
 
 import android.app.LoaderManager;
-import androidx.lifecycle.OnLifecycleEvent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Loader;
 import android.os.Bundle;
 import android.service.settings.suggestions.Suggestion;
-import androidx.annotation.Nullable;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+import androidx.lifecycle.OnLifecycleEvent;
+
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import java.util.List;
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
index 1791217..eea49bc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompat.java
@@ -23,15 +23,15 @@
 import android.service.settings.suggestions.Suggestion;
 import android.util.Log;
 
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import java.util.List;
-
 import androidx.annotation.Nullable;
 import androidx.lifecycle.OnLifecycleEvent;
 import androidx.loader.app.LoaderManager;
 import androidx.loader.content.Loader;
 
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.List;
+
 /**
  * Manages IPC communication to SettingsIntelligence for suggestion related services.
  */
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
index 7cdbe71..9451b36 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
@@ -31,12 +31,13 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 
+import androidx.annotation.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/IconCache.java b/packages/SettingsLib/src/com/android/settingslib/utils/IconCache.java
index f0548ff..c8c8ac2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/IconCache.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/IconCache.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.collection.ArrayMap;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index e16da84..fa59688 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -22,9 +22,10 @@
 import android.icu.text.MeasureFormat.FormatWidth;
 import android.icu.util.Measure;
 import android.icu.util.MeasureUnit;
-import androidx.annotation.Nullable;
 import android.text.TextUtils;
 
+import androidx.annotation.Nullable;
+
 import com.android.settingslib.R;
 
 import java.time.Instant;
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
index 87a56c75..f02044d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreference.java
@@ -17,13 +17,14 @@
 package com.android.settingslib.widget;
 
 import android.content.Context;
-import androidx.core.content.res.TypedArrayUtils;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.text.method.LinkMovementMethod;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
 import com.android.settingslib.R;
 
 /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
index 5883754..2987c15 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.widget;
 
 import android.content.Context;
+
 import androidx.preference.PreferenceFragment;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
index 260ac83..d45e56d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
@@ -18,13 +18,13 @@
 
 import android.content.Context;
 
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
 
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-
 public class FooterPreferenceMixinCompat implements LifecycleObserver, SetPreferenceScreen {
 
     private final PreferenceFragmentCompat mFragment;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 18a44ed..e950e8e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -48,14 +48,12 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import androidx.annotation.NonNull;
-import android.text.Spannable;
-import android.text.SpannableString;
 import android.text.TextUtils;
-import android.text.style.TtsSpan;
 import android.util.ArraySet;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.R;
 import com.android.settingslib.utils.ThreadUtils;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index aa29f5a..f3c43cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -25,9 +25,6 @@
 import android.net.wifi.WifiConfiguration;
 import android.os.Looper;
 import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.SparseArray;
@@ -35,9 +32,12 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
 import com.android.settingslib.R;
 import com.android.settingslib.TronUtils;
-import com.android.settingslib.TwoTargetPreference;
 import com.android.settingslib.Utils;
 import com.android.settingslib.wifi.AccessPoint.Speed;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index 5862e6f..afea5d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -24,6 +24,7 @@
 import android.net.wifi.WifiInfo;
 import android.os.Bundle;
 import android.os.Parcelable;
+
 import androidx.annotation.Keep;
 
 import com.android.settingslib.wifi.AccessPoint.Speed;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 6211d12..9050b4b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -41,15 +41,16 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
-import androidx.annotation.GuardedBy;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.widget.Toast;
 
+import androidx.annotation.GuardedBy;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settingslib.R;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
index e73d952..93e4fce 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTrackerFactory.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.wifi;
 
 import android.content.Context;
+
 import androidx.annotation.Keep;
 import androidx.annotation.NonNull;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index 4792317..4e6c005 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -21,6 +21,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.os.SystemClock;
+
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 710dbc22..bf49ef3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -20,8 +20,11 @@
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
+
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
index f00ae0b..79d682d6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
@@ -24,11 +24,12 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
 import android.view.View;
 import android.widget.TextView;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
index fc0203a..e70baa1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
@@ -23,9 +23,9 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.net.ConnectivityManager;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
index efd7de3..c0b69f2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
@@ -19,16 +19,19 @@
 import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_DEFAULT;
 import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_MEDIUM;
 import static com.android.settingslib.TwoTargetPreference.ICON_SIZE_SMALL;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
-import androidx.preference.PreferenceViewHolder;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
+import androidx.preference.PreferenceViewHolder;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index babe82e..47e51f3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -20,6 +20,7 @@
 import static com.android.settingslib.Utils.STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
index 2dbabe0..19ce4242 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
@@ -25,7 +25,6 @@
 
 import android.annotation.UserIdInt;
 import android.app.ApplicationPackageManager;
-import android.app.usage.IStorageStatsManager;
 import android.app.usage.StorageStats;
 import android.app.usage.StorageStatsManager;
 import android.content.ComponentName;
@@ -42,10 +41,10 @@
 import android.os.UserHandle;
 import android.util.IconDrawableFactory;
 
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 import com.android.settingslib.applications.ApplicationsState.Callbacks;
 import com.android.settingslib.applications.ApplicationsState.Session;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.testutils.shadow.ShadowUserManager;
 
 import org.junit.Before;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index 060b716..d8c459c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.applications;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index f223176..5550b7e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -79,6 +79,8 @@
                 mContext));
         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
+        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager);
     }
 
     /**
@@ -88,20 +90,26 @@
     public void constructor_initiateHidAndHidDeviceProfile() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.HID_HOST, BluetoothProfile.HID_DEVICE}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
 
         assertThat(mProfileManager.getHidProfile()).isNotNull();
         assertThat(mProfileManager.getHidDeviceProfile()).isNotNull();
     }
 
+    @Test
+    public void constructor_doNotUpdateProfiles() {
+        mProfileManager = spy(new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
+                mDeviceManager, mEventManager));
+
+        verify(mProfileManager, never()).updateLocalProfiles();
+    }
+
     /**
      * Verify updateLocalProfiles() for a local A2DP source adds A2dpProfile
      */
     @Test
     public void updateLocalProfiles_addA2dpToLocalProfiles() {
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         assertThat(mProfileManager.getA2dpProfile()).isNull();
         assertThat(mProfileManager.getHeadsetProfile()).isNull();
 
@@ -120,8 +128,7 @@
     public void updateProfiles_addHidProfileForRemoteDevice() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.HID_HOST}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         ParcelUuid[] uuids = new ParcelUuid[]{BluetoothUuid.Hid};
         ParcelUuid[] localUuids = new ParcelUuid[]{};
         List<LocalBluetoothProfile> profiles = new ArrayList<>();
@@ -143,8 +150,7 @@
     public void stateChangedHandler_receiveA2dpConnectionStateChanged_shouldDispatchCallback() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.A2DP}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -167,8 +173,7 @@
     public void stateChangedHandler_receiveHeadsetConnectionStateChanged_shouldDispatchCallback() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.HEADSET}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -191,8 +196,7 @@
     public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.HEARING_AID}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -215,8 +219,7 @@
     public void stateChangedHandler_receivePanConnectionStateChanged_shouldNotDispatchCallback() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.PAN}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -239,8 +242,7 @@
     public void stateChangedHandler_receivePanConnectionStateChangedWithoutProfile_shouldNotRefresh
     () {
         mShadowBluetoothAdapter.setSupportedProfiles(null);
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
@@ -262,8 +264,7 @@
     public void stateChangedHandler_receivePanConnectionStateChangedWithProfile_shouldRefresh() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.PAN}));
-        mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
-                mDeviceManager, mEventManager);
+        mProfileManager.updateLocalProfiles();
         // Refer to BluetoothControllerImpl, it will call setReceiverHandler after
         // LocalBluetoothProfileManager created.
         mEventManager.setReceiverHandler(null);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 5c19e61..f4fd779 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.core.instrumentation;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index 017d373..be671e6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -15,10 +15,15 @@
  */
 package com.android.settingslib.core.instrumentation;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+        .ACTION_SETTINGS_PREFERENCE_CHANGE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+        .FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+        .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+        .FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.argThat;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
index f34c338..f78573a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.core.instrumentation;
 
 import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
+
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -30,6 +31,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
+
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.internal.logging.nano.MetricsProto;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index 28828a0..c23ad79 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.core.lifecycle;
 
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
@@ -25,6 +26,8 @@
 import android.view.MenuItem;
 import android.widget.LinearLayout;
 
+import androidx.lifecycle.LifecycleOwner;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.events.OnAttach;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
@@ -43,8 +46,6 @@
 import org.robolectric.Robolectric;
 import org.robolectric.android.controller.ActivityController;
 
-import androidx.lifecycle.LifecycleOwner;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class LifecycleTest {
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
index 7c65335..2a608399 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.development;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
@@ -26,9 +27,10 @@
 import android.content.pm.PackageManager;
 import android.os.UserManager;
 import android.provider.Settings;
-import androidx.preference.SwitchPreference;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
index ae3072c..2f78899 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
@@ -40,6 +40,7 @@
 
 import android.content.Context;
 import android.os.SystemProperties;
+
 import androidx.preference.ListPreference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
index b0aaa25..ed128e0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
@@ -17,12 +17,14 @@
 package com.android.settingslib.development;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
-import androidx.lifecycle.LifecycleOwner;
 import android.os.SystemProperties;
+
+import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.ListPreference;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
index 8ec7149..234b4d5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
@@ -22,6 +22,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
index 7c127e5..aee956c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doReturn;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
index cb7861b..2b490ee 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
@@ -17,17 +17,19 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 import android.content.Context;
 import android.os.PersistableBundle;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
index 8f144cd..1d957c3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
index 69fb86e..dc77400 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
@@ -17,9 +17,11 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
index eaae405..eb77cb6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.deviceinfo;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.robolectric.shadow.api.Shadow.extract;
 
 import android.net.ConnectivityManager;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
index 20ce465..2e0348d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
@@ -23,9 +23,10 @@
 
 import android.content.Context;
 import android.os.SystemClock;
+import android.text.format.DateUtils;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
-import android.text.format.DateUtils;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
index 757df5b..359ea77 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
@@ -27,6 +28,7 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.provider.Settings;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
index eb7ad6d..ca621ca 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.display;
 
 import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index c495511..59a3dd6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -24,7 +24,6 @@
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
 
 import java.util.Set;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index ba5a2c5..de96af4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -17,8 +17,8 @@
 package com.android.settingslib.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.eq;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 23087a9..9b1fe5f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.fuelgauge;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doNothing;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 8a54aee..9c168f7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -1,6 +1,7 @@
 package com.android.settingslib.location;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.isA;
 import static org.mockito.Mockito.when;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index ccd2f53..89c319a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -20,6 +20,7 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index f47f41c..8147656 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -19,26 +19,15 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
 
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.NotificationManager;
-import android.content.Context;
+import static org.mockito.Mockito.spy;
+
 import android.content.ContentResolver;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.net.Uri;
+import android.content.Context;
 import android.provider.Settings;
 import android.service.notification.Condition;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.Button;
 
 import androidx.appcompat.app.AlertDialog;
 
@@ -47,9 +36,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
index 1ee3afa..449451a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
@@ -18,7 +18,9 @@
 
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -26,6 +28,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.loader.app.LoaderManager;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -38,9 +43,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import androidx.lifecycle.LifecycleOwner;
-import androidx.loader.app.LoaderManager;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
 @Config(shadows = ShadowSuggestionController.class)
 public class SuggestionControllerMixinCompatTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
index f486989..aac582f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
@@ -18,16 +18,19 @@
 
 import static androidx.lifecycle.Lifecycle.Event.ON_START;
 import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.LoaderManager;
-import androidx.lifecycle.LifecycleOwner;
 import android.content.ComponentName;
 import android.content.Context;
 
+import androidx.lifecycle.LifecycleOwner;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
index 8ba8606..d8e73b7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/FragmentTestUtils.java
@@ -19,12 +19,12 @@
 import android.os.Bundle;
 import android.widget.LinearLayout;
 
-import org.robolectric.Robolectric;
-
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentManager;
 
+import org.robolectric.Robolectric;
+
 /**
  * Utilities for creating Fragments for testing.
  * <p>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
index 890abef..4705cd2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
@@ -22,14 +22,13 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
-
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
 
-import com.android.settingslib.testutils.shadow.ShadowActivityManager;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowActivityManager;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index f2ef99c..6a9579b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.utils;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index 743951a..e4bbbcb 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.utils;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.spy;
 
 import android.content.Context;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
index 1abbaba..f56c111 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
@@ -17,12 +17,18 @@
 package com.android.settingslib.widget;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -33,11 +39,6 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.shadows.ShadowApplication;
 
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class FooterPreferenceMixinCompatTest {
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 8604d18..366b720 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -17,12 +17,18 @@
 package com.android.settingslib.widget;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import androidx.lifecycle.LifecycleOwner;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -33,11 +39,6 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.shadows.ShadowApplication;
 
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class FooterPreferenceMixinTest {
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
index 3280089..84a043e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
@@ -19,11 +19,12 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
-import androidx.preference.PreferenceViewHolder;
 import android.text.method.LinkMovementMethod;
 import android.view.LayoutInflater;
 import android.widget.TextView;
 
+import androidx.preference.PreferenceViewHolder;
+
 import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index ee2c2ff..86443bd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.wifi;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
index d25adde..07c50fd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
@@ -16,6 +16,7 @@
 package com.android.settingslib.wifi;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
deleted file mode 100644
index 9c9b929..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NoisyVelocityTracker.java
+++ /dev/null
@@ -1,135 +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
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.util.Log;
-import android.util.Pools;
-import android.view.MotionEvent;
-
-import java.util.ArrayDeque;
-import java.util.Iterator;
-
-/**
- * A very simple low-pass velocity filter for motion events for noisy touch screens.
- */
-public class NoisyVelocityTracker implements VelocityTrackerInterface {
-
-    private static final Pools.SynchronizedPool<NoisyVelocityTracker> sNoisyPool =
-            new Pools.SynchronizedPool<>(2);
-
-    private static final float DECAY = 0.75f;
-    private static final boolean DEBUG = false;
-
-    private final int MAX_EVENTS = 8;
-    private ArrayDeque<MotionEventCopy> mEventBuf = new ArrayDeque<MotionEventCopy>(MAX_EVENTS);
-    private float mVX, mVY = 0;
-
-    private static class MotionEventCopy {
-        public MotionEventCopy(float x2, float y2, long eventTime) {
-            this.x = x2;
-            this.y = y2;
-            this.t = eventTime;
-        }
-        float x, y;
-        long t;
-    }
-
-    public static NoisyVelocityTracker obtain() {
-        NoisyVelocityTracker instance = sNoisyPool.acquire();
-        return (instance != null) ? instance : new NoisyVelocityTracker();
-    }
-
-    private NoisyVelocityTracker() {
-    }
-
-    public void addMovement(MotionEvent event) {
-        if (mEventBuf.size() == MAX_EVENTS) {
-            mEventBuf.remove();
-        }
-        mEventBuf.add(new MotionEventCopy(event.getRawX(), event.getRawY(), event.getEventTime()));
-    }
-
-    public void computeCurrentVelocity(int units) {
-        if (NoisyVelocityTracker.DEBUG) {
-            Log.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
-        }
-        mVX = mVY = 0;
-        MotionEventCopy last = null;
-        int i = 0;
-        float totalweight = 0f;
-        float weight = 10f;
-        for (final Iterator<MotionEventCopy> iter = mEventBuf.iterator();
-                iter.hasNext();) {
-            final MotionEventCopy event = iter.next();
-            if (last != null) {
-                final float dt = (float) (event.t - last.t) / units;
-                final float dx = (event.x - last.x);
-                final float dy = (event.y - last.y);
-                if (NoisyVelocityTracker.DEBUG) {
-                    Log.v("FlingTracker", String.format(
-                            "   [%d] (t=%d %.1f,%.1f) dx=%.1f dy=%.1f dt=%f vx=%.1f vy=%.1f",
-                            i, event.t, event.x, event.y,
-                            dx, dy, dt,
-                            (dx/dt),
-                            (dy/dt)
-                    ));
-                }
-                if (event.t == last.t) {
-                    // Really not sure what to do with events that happened at the same time,
-                    // so we'll skip subsequent events.
-                    continue;
-                }
-                mVX += weight * dx / dt;
-                mVY += weight * dy / dt;
-                totalweight += weight;
-                weight *= DECAY;
-            }
-            last = event;
-            i++;
-        }
-        if (totalweight > 0) {
-            mVX /= totalweight;
-            mVY /= totalweight;
-        } else {
-            // so as not to contaminate the velocities with NaN
-            mVX = mVY = 0;
-        }
-
-        if (NoisyVelocityTracker.DEBUG) {
-            Log.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
-        }
-    }
-
-    public float getXVelocity() {
-        if (Float.isNaN(mVX) || Float.isInfinite(mVX)) {
-            mVX = 0;
-        }
-        return mVX;
-    }
-
-    public float getYVelocity() {
-        if (Float.isNaN(mVY) || Float.isInfinite(mVX)) {
-            mVY = 0;
-        }
-        return mVY;
-    }
-
-    public void recycle() {
-        mEventBuf.clear();
-        sNoisyPool.release(this);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index bef34f6..57c2439 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 import android.view.InputDevice;
 import android.view.MotionEvent;
+import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
@@ -103,7 +104,7 @@
 
     private ValueAnimator mHeightAnimator;
     private ObjectAnimator mPeekAnimator;
-    private VelocityTrackerInterface mVelocityTracker;
+    private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
     private FlingAnimationUtils mFlingAnimationUtils;
     private FlingAnimationUtils mFlingAnimationUtilsClosing;
     private FlingAnimationUtils mFlingAnimationUtilsDismissing;
@@ -226,10 +227,6 @@
         mUnlockFalsingThreshold = res.getDimensionPixelSize(R.dimen.unlock_falsing_threshold);
     }
 
-    private void trackMovement(MotionEvent event) {
-        if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
-    }
-
     public void setTouchAndAnimationDisabled(boolean disabled) {
         mTouchDisabled = disabled;
         if (mTouchDisabled) {
@@ -310,10 +307,7 @@
                 mTouchAboveFalsingThreshold = false;
                 mCollapsedAndHeadsUpOnDown = isFullyCollapsed()
                         && mHeadsUpManager.hasPinnedHeadsUp();
-                if (mVelocityTracker == null) {
-                    initVelocityTracker();
-                }
-                trackMovement(event);
+                mVelocityTracker.addMovement(event);
                 if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)
                         || mPeekAnimator != null) {
                     mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
@@ -347,7 +341,7 @@
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
-                trackMovement(event);
+                mVelocityTracker.addMovement(event);
                 float h = y - mInitialTouchY;
 
                 // If the panel was collapsed when touching, we only need to check for the
@@ -392,7 +386,7 @@
 
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                trackMovement(event);
+                mVelocityTracker.addMovement(event);
                 endMotionEvent(event, x, y, false /* forceCancel */);
                 break;
         }
@@ -458,14 +452,11 @@
                 || Math.abs(y - mInitialTouchY) > mTouchSlop
                 || event.getActionMasked() == MotionEvent.ACTION_CANCEL
                 || forceCancel) {
-            float vel = 0f;
-            float vectorVel = 0f;
-            if (mVelocityTracker != null) {
-                mVelocityTracker.computeCurrentVelocity(1000);
-                vel = mVelocityTracker.getYVelocity();
-                vectorVel = (float) Math.hypot(
-                        mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
-            }
+            mVelocityTracker.computeCurrentVelocity(1000);
+            float vel = mVelocityTracker.getYVelocity();
+            float vectorVel = (float) Math.hypot(
+                    mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
+
             boolean expand = flingExpands(vel, vectorVel, x, y)
                     || event.getActionMasked() == MotionEvent.ACTION_CANCEL
                     || forceCancel;
@@ -502,17 +493,11 @@
             onTrackingStopped(expands);
         }
 
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-        }
+        mVelocityTracker.clear();
         mPeekTouching = false;
     }
 
     protected float getCurrentExpandVelocity() {
-        if (mVelocityTracker == null) {
-            return 0;
-        }
         mVelocityTracker.computeCurrentVelocity(1000);
         return mVelocityTracker.getYVelocity();
     }
@@ -588,8 +573,7 @@
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mTouchAboveFalsingThreshold = false;
-                initVelocityTracker();
-                trackMovement(event);
+                mVelocityTracker.addMovement(event);
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 final int upPointer = event.getPointerId(event.getActionIndex());
@@ -604,15 +588,12 @@
             case MotionEvent.ACTION_POINTER_DOWN:
                 if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                     mMotionAborted = true;
-                    if (mVelocityTracker != null) {
-                        mVelocityTracker.recycle();
-                        mVelocityTracker = null;
-                    }
+                    mVelocityTracker.clear();
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
                 final float h = y - mInitialTouchY;
-                trackMovement(event);
+                mVelocityTracker.addMovement(event);
                 if (scrolledToBottom || mTouchStartedInEmptyArea || mAnimatingOnDown) {
                     float hAbs = Math.abs(h);
                     if ((h < -mTouchSlop || (mAnimatingOnDown && hAbs > mTouchSlop))
@@ -625,10 +606,7 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                if (mVelocityTracker != null) {
-                    mVelocityTracker.recycle();
-                    mVelocityTracker = null;
-                }
+                mVelocityTracker.clear();
                 break;
         }
         return false;
@@ -656,13 +634,6 @@
         }
     }
 
-    private void initVelocityTracker() {
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-        }
-        mVelocityTracker = VelocityTrackerFactory.obtain(getContext());
-    }
-
     protected boolean isScrolledToBottom() {
         return true;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java
deleted file mode 100644
index f589c3d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PlatformVelocityTracker.java
+++ /dev/null
@@ -1,72 +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
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.util.Pools;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-
-/**
- * An implementation of {@link VelocityTrackerInterface} using the platform-standard
- * {@link VelocityTracker}.
- */
-public class PlatformVelocityTracker implements VelocityTrackerInterface {
-
-    private static final Pools.SynchronizedPool<PlatformVelocityTracker> sPool =
-            new Pools.SynchronizedPool<>(2);
-
-    private VelocityTracker mTracker;
-
-    public static PlatformVelocityTracker obtain() {
-        PlatformVelocityTracker tracker = sPool.acquire();
-        if (tracker == null) {
-            tracker = new PlatformVelocityTracker();
-        }
-        tracker.setTracker(VelocityTracker.obtain());
-        return tracker;
-    }
-
-    public void setTracker(VelocityTracker tracker) {
-        mTracker = tracker;
-    }
-
-    @Override
-    public void addMovement(MotionEvent event) {
-        mTracker.addMovement(event);
-    }
-
-    @Override
-    public void computeCurrentVelocity(int units) {
-        mTracker.computeCurrentVelocity(units);
-    }
-
-    @Override
-    public float getXVelocity() {
-        return mTracker.getXVelocity();
-    }
-
-    @Override
-    public float getYVelocity() {
-        return mTracker.getYVelocity();
-    }
-
-    @Override
-    public void recycle() {
-        mTracker.recycle();
-        sPool.release(this);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java
deleted file mode 100644
index e153b85..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerFactory.java
+++ /dev/null
@@ -1,42 +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
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-
-import com.android.systemui.R;
-
-/**
- * A class to generate {@link VelocityTrackerInterface}, depending on the configuration.
- */
-public class VelocityTrackerFactory {
-
-    public static final String PLATFORM_IMPL = "platform";
-    public static final String NOISY_IMPL = "noisy";
-
-    public static VelocityTrackerInterface obtain(Context ctx) {
-        String tracker = ctx.getResources().getString(R.string.velocity_tracker_impl);
-        switch (tracker) {
-            case NOISY_IMPL:
-                return NoisyVelocityTracker.obtain();
-            case PLATFORM_IMPL:
-                return PlatformVelocityTracker.obtain();
-            default:
-                throw new IllegalStateException("Invalid tracker: " + tracker);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java
deleted file mode 100644
index a54b054..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VelocityTrackerInterface.java
+++ /dev/null
@@ -1,31 +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
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.view.MotionEvent;
-
-/**
- * An interface for a velocity tracker to delegate. To be implemented by different velocity tracking
- * algorithms.
- */
-public interface VelocityTrackerInterface {
-    public void addMovement(MotionEvent event);
-    public void computeCurrentVelocity(int units);
-    public float getXVelocity();
-    public float getYVelocity();
-    public void recycle();
-}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 5771748..af33bd0 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -978,12 +978,12 @@
                 throw new IllegalArgumentException(packageName + " is not a valid package", e);
             }
 
-            // TODO(b/112051762): rather than always call AM here, call it on demand on
+            // TODO(b/113281366): rather than always call AM here, call it on demand on
             // getPreviousSessionsLocked()? That way we save space / time here, and don't set
             // a callback on AM unnecessarily (see TODO below :-)
             final ActivityManagerInternal am = LocalServices
                     .getService(ActivityManagerInternal.class);
-            // TODO(b/112051762): add a callback method on AM to be notified when a task is finished
+            // TODO(b/113281366): add a callback method on AM to be notified when a task is finished
             // so we can clean up sessions kept alive
             final int taskId = am.getTaskIdForActivity(activityToken, false);
             final int sessionId;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 48b3798..8c8352f 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -617,7 +617,7 @@
         ArrayList<Session> previousSessions = null;
         for (int i = 0; i < size; i++) {
             final Session previousSession = mSessions.valueAt(i);
-            // TODO(b/112051762): only return sessions asked to be kept alive / add CTS test
+            // TODO(b/113281366): only return sessions asked to be kept alive / add CTS test
             if (previousSession.taskId == session.taskId && previousSession.id != session.id) {
                 if (previousSessions == null) {
                     previousSessions = new ArrayList<>(size);
@@ -625,7 +625,7 @@
                 previousSessions.add(previousSession);
             }
         }
-        // TODO(b/112051762): remove returned sessions / add CTS test
+        // TODO(b/113281366): remove returned sessions / add CTS test
         return previousSessions;
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
index 8ee6571..293f908e 100644
--- a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -17,8 +17,8 @@
 
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
-import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_AVAILABLE_ALGORITHMS;
-import static android.service.autofill.AutofillFieldClassificationService.RESOURCE_DEFAULT_ALGORITHM;
+import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
+import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM;
 
 import android.Manifest;
 import android.annotation.MainThread;
@@ -226,7 +226,7 @@
      */
     @Nullable
     String[] getAvailableAlgorithms() {
-        return getMetadataValue(RESOURCE_AVAILABLE_ALGORITHMS, "array",
+        return getMetadataValue(SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS,
                 (res, id) -> res.getStringArray(id));
     }
 
@@ -235,12 +235,11 @@
      */
     @Nullable
     String getDefaultAlgorithm() {
-        return getMetadataValue(RESOURCE_DEFAULT_ALGORITHM, "string",
-                (res, id) -> res.getString(id));
+        return getMetadataValue(SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id));
     }
 
     @Nullable
-    private <T> T getMetadataValue(String field, String type, MetadataParser<T> parser) {
+    private <T> T getMetadataValue(String field, MetadataParser<T> parser) {
         final ServiceInfo serviceInfo = getServiceInfo();
         if (serviceInfo == null) return null;
 
@@ -254,7 +253,7 @@
             return null;
         }
 
-        final int resourceId = res.getIdentifier(field, type, serviceInfo.packageName);
+        final int resourceId = serviceInfo.metaData.getInt(field);
         return parser.get(res, resourceId);
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 5a10c1e..5b7332d 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -75,6 +75,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -329,12 +330,9 @@
                     fillContextWithAllowedValuesLocked(mContexts.get(i), flags);
                 }
 
-                // Dispatch a snapshot of the current contexts list since it may change
-                // until the dispatch happens. The items in the list don't need to be cloned
-                // since we don't hold on them anywhere else. The client state is not touched
-                // by us, so no need to copy.
-                request = new FillRequest(requestId, new ArrayList<>(mContexts), mClientState,
-                        flags);
+                final ArrayList<FillContext> contexts =
+                        mergePreviousSessionLocked(/* forSave= */ false);
+                request = new FillRequest(requestId, contexts, mClientState, flags);
             }
 
             mRemoteFillService.onFillRequest(request);
@@ -1465,7 +1463,7 @@
         }
 
         if ((saveInfo.getFlags() & SaveInfo.FLAG_DELAY_SAVE) != 0) {
-            // TODO(b/112051762): log metrics
+            // TODO(b/113281366): log metrics
             if (sDebug) Slog.v(TAG, "showSaveLocked(): service asked to delay save");
             return false;
         }
@@ -1890,13 +1888,38 @@
         // Remove pending fill requests as the session is finished.
         cancelCurrentRequestLocked();
 
-        // Merge the previous sessions that the service asked to be kept alive
+        final ArrayList<FillContext> contexts = mergePreviousSessionLocked( /* forSave= */ true);
+
+        final SaveRequest saveRequest =
+                new SaveRequest(contexts, mClientState, mSelectedDatasetIds);
+        mRemoteFillService.onSaveRequest(saveRequest);
+    }
+
+    // TODO(b/113281366): rather than merge it here, it might be better to simply reuse the old
+    // session instead of creating a new one. But we need to consider what would happen on corner
+    // cases such as "Main Activity M -> activity A with username -> activity B with password"
+    // If user follows the normal workflow, than session A would be merged with session B as
+    // expected. But if when on Activity A the user taps back or somehow launches another activity,
+    // session A could be merged with the wrong session.
+    /**
+     * Gets a list of contexts that includes not only this session's contexts but also the contexts
+     * from previous sessions that were asked by the service to be delayed (if any).
+     *
+     * <p>As a side-effect:
+     * <ul>
+     *   <li>If the current {@link #mClientState} is {@code null}, sets it with the last non-
+     *   {@code null} client state from previous sessions.
+     *   <li>When {@code forSave} is {@code true}, calls {@link #updateValuesForSaveLocked()} in the
+     *   previous sessions.
+     * </ul>
+     */
+    @NonNull
+    private ArrayList<FillContext> mergePreviousSessionLocked(boolean forSave) {
         final ArrayList<Session> previousSessions = mService.getPreviousSessionsLocked(this);
         final ArrayList<FillContext> contexts;
-        final Bundle clientState;
         if (previousSessions != null) {
             if (sDebug) {
-                Slog.d(TAG, "callSaveLocked(): Merging the content of " + previousSessions.size()
+                Slog.d(TAG, "mergeSessions(): Merging the content of " + previousSessions.size()
                         + " sessions for task " + taskId);
             }
             contexts = new ArrayList<>();
@@ -1904,31 +1927,35 @@
                 final Session previousSession = previousSessions.get(i);
                 final ArrayList<FillContext> previousContexts = previousSession.mContexts;
                 if (previousContexts == null) {
-                    Slog.w(TAG, "callSaveLocked(): Not merging null contexts from "
+                    Slog.w(TAG, "mergeSessions(): Not merging null contexts from "
                             + previousSession.id);
                     continue;
                 }
-                previousSession.updateValuesForSaveLocked();
-                if (sVerbose) {
-                    Slog.v(TAG, "callSaveLocked(): adding " + previousContexts.size()
+                if (forSave) {
+                    previousSession.updateValuesForSaveLocked();
+                }
+                if (sDebug) {
+                    Slog.d(TAG, "mergeSessions(): adding " + previousContexts.size()
                             + " context from previous session #" + previousSession.id);
                 }
                 contexts.addAll(previousContexts);
+                if (mClientState == null && previousSession.mClientState != null) {
+                    if (sDebug) {
+                        Slog.d(TAG, "mergeSessions(): setting client state from previous session"
+                                + previousSession.id);
+                    }
+                    mClientState = previousSession.mClientState;
+                }
             }
             contexts.addAll(mContexts);
-            // TODO(b/112051762): decided what to do with client state / add CTS test
-            clientState = mClientState;
         } else {
             // Dispatch a snapshot of the current contexts list since it may change
             // until the dispatch happens. The items in the list don't need to be cloned
             // since we don't hold on them anywhere else. The client state is not touched
             // by us, so no need to copy.
             contexts = new ArrayList<>(mContexts);
-            clientState = mClientState;
         }
-
-        final SaveRequest saveRequest = new SaveRequest(contexts, clientState, mSelectedDatasetIds);
-        mRemoteFillService.onSaveRequest(saveRequest);
+        return contexts;
     }
 
     /**
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 713da30..aaca85b 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -17,34 +17,33 @@
 package com.android.server;
 
 import android.app.IActivityController;
-import android.os.Binder;
-import android.os.Build;
-import android.os.RemoteException;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructRlimit;
-import com.android.internal.os.ZygoteConnectionConstants;
-import com.android.server.am.ActivityManagerService;
-
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hidl.manager.V1_0.IServiceManager;
+import android.os.Binder;
+import android.os.Build;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.os.SystemProperties;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructRlimit;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.os.ZygoteConnectionConstants;
+import com.android.server.am.ActivityManagerService;
+
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -62,6 +61,8 @@
 public class Watchdog extends Thread {
     static final String TAG = "Watchdog";
 
+    private static final boolean DEBUG = true; // STOPSHIP disable it (b/113252928)
+
     // Set this to true to use debug default values.
     static final boolean DB = false;
 
@@ -478,6 +479,7 @@
                         continue;
                     } else if (waitState == WAITED_HALF) {
                         if (!waitedHalf) {
+                            if (DEBUG) Slog.d(TAG, "WAITED_HALF");
                             // We've waited half the deadlock-detection interval.  Pull a stack
                             // trace and wait another half.
                             ArrayList<Integer> pids = new ArrayList<Integer>();
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 0a7d3fd..0e63d0c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -46,7 +46,7 @@
 
     // Available log categories in the activity manager package.
     static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
-    static final boolean DEBUG_ANR = false;
+    static final boolean DEBUG_ANR = true;  // STOPSHIP disable it (b/113252928)
     static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false;
     static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 82805ed..1bc0524 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1618,6 +1618,9 @@
                 break;
             }
             case DISPATCH_UIDS_CHANGED_UI_MSG: {
+                if (false) { // DO NOT SUBMIT WITH TRUE
+                    maybeTriggerWatchdog();
+                }
                 dispatchUidsChanged();
             } break;
             case DISPATCH_OOM_ADJ_OBSERVER_MSG: {
@@ -21551,4 +21554,20 @@
             return superImpl.apply(permName, uid);
         }
     }
+
+    /**
+     * If debug.trigger.watchdog is set to 1, sleep 10 minutes with the AM lock held, which would
+     * cause a watchdog kill.
+     */
+    void maybeTriggerWatchdog() {
+        if (SystemProperties.getInt("debug.trigger.watchdog", 0) == 1) {
+            Slog.w(TAG, "TRIGGERING WATCHDOG");
+            synchronized (ActivityManagerService.this) {
+                try {
+                    Thread.sleep(600 * 1000);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index c0beb37..b8f057d 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -35,7 +35,6 @@
 import android.net.Network;
 import android.net.NetworkUtils;
 import android.net.Uri;
-import android.net.dns.ResolvUtil;
 import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.os.UserHandle;
@@ -174,15 +173,6 @@
         return new PrivateDnsConfig(useTls);
     }
 
-    public static PrivateDnsConfig tryBlockingResolveOf(Network network, String name) {
-        try {
-            final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(network, name);
-            return new PrivateDnsConfig(name, ips);
-        } catch (UnknownHostException uhe) {
-            return new PrivateDnsConfig(name, null);
-        }
-    }
-
     public static Uri[] getPrivateDnsSettingsUris() {
         return new Uri[]{
             Settings.Global.getUriFor(PRIVATE_DNS_DEFAULT_MODE),
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 843ba2e..ca9b256 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -43,7 +43,6 @@
 import android.net.Uri;
 import android.net.captiveportal.CaptivePortalProbeResult;
 import android.net.captiveportal.CaptivePortalProbeSpec;
-import android.net.dns.ResolvUtil;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
 import android.net.metrics.ValidationProbeEvent;
@@ -326,7 +325,7 @@
         mConnectivityServiceHandler = handler;
         mDependencies = deps;
         mNetworkAgentInfo = networkAgentInfo;
-        mNetwork = deps.getNetwork(networkAgentInfo);
+        mNetwork = deps.getNetwork(networkAgentInfo).getPrivateDnsBypassingCopy();
         mNetId = mNetwork.netId;
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -800,9 +799,7 @@
         private void resolveStrictModeHostname() {
             try {
                 // Do a blocking DNS resolution using the network-assigned nameservers.
-                // Do not set AI_ADDRCONFIG in ai_flags so we get all address families in advance.
-                final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(
-                        mNetwork, mPrivateDnsProviderHostname, 0 /* aiFlags */);
+                final InetAddress[] ips = mNetwork.getAllByName(mPrivateDnsProviderHostname);
                 mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
                 validationLog("Strict mode hostname resolved: " + mPrivateDnsConfig);
             } catch (UnknownHostException uhe) {
@@ -860,14 +857,13 @@
     // to complete, regardless of how many IP addresses a host has.
     private static class OneAddressPerFamilyNetwork extends Network {
         public OneAddressPerFamilyNetwork(Network network) {
-            super(network);
+            // Always bypass Private DNS.
+            super(network.getPrivateDnsBypassingCopy());
         }
 
         @Override
         public InetAddress[] getAllByName(String host) throws UnknownHostException {
-            // Always bypass Private DNS.
-            final List<InetAddress> addrs = Arrays.asList(
-                    ResolvUtil.blockingResolveAllLocally(this, host));
+            final List<InetAddress> addrs = Arrays.asList(super.getAllByName(host));
 
             // Ensure the address family of the first address is tried first.
             LinkedHashMap<Class, InetAddress> addressByFamily = new LinkedHashMap<>();
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 2c9a494..c145d646 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1305,14 +1305,16 @@
         }
         final ActivityManagerInternal ami =
                 LocalServices.getService(ActivityManagerInternal.class);
-        final int procState = (ami != null)
-                ? ami.getUidProcessState(callingUid)
-                : ActivityManager.PROCESS_STATE_NONEXISTENT;
+        if (ami == null) {
+            return ContentResolver.SYNC_EXEMPTION_NONE;
+        }
+        final int procState = ami.getUidProcessState(callingUid);
+        final boolean isUidActive = ami.isUidActive(callingUid);
 
         if (procState <= ActivityManager.PROCESS_STATE_TOP) {
             return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
         }
-        if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+        if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND || isUidActive) {
             return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
         }
         return ContentResolver.SYNC_EXEMPTION_NONE;
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 59673d0..556038f 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
+import android.app.PendingIntent;
 import android.app.ProcessMemoryState;
 import android.app.StatsManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -43,7 +44,6 @@
 import android.os.IBinder;
 import android.os.IStatsCompanionService;
 import android.os.IStatsManager;
-import android.os.IStoraged;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
@@ -55,7 +55,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.storage.StorageManager;
 import android.telephony.ModemActivityInfo;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
@@ -66,10 +65,10 @@
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.os.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
-import com.android.internal.os.KernelUidCpuActiveTimeReader;
-import com.android.internal.os.KernelUidCpuClusterTimeReader;
-import com.android.internal.os.KernelUidCpuFreqTimeReader;
 import com.android.internal.os.KernelUidCpuTimeReader;
+import com.android.internal.os.KernelUidCpuClusterTimeReader;
+import com.android.internal.os.KernelUidCpuActiveTimeReader;
+import com.android.internal.os.KernelUidCpuFreqTimeReader;
 import com.android.internal.os.KernelWakelockReader;
 import com.android.internal.os.KernelWakelockStats;
 import com.android.internal.os.PowerProfile;
@@ -77,18 +76,9 @@
 import com.android.server.BinderCallsStatsService;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
-import com.android.server.storage.DiskStatsFileLogger;
-import com.android.server.storage.DiskStatsLoggingService;
-
-import libcore.io.IoUtils;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -874,6 +864,14 @@
         pulledData.add(e);
     }
 
+    private void pullDiskSpace(int tagId, List<StatsLogEventWrapper> pulledData) {
+        StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 3);
+        e.writeLong(mStatFsData.getAvailableBytes());
+        e.writeLong(mStatFsSystem.getAvailableBytes());
+        e.writeLong(mStatFsTemp.getAvailableBytes());
+        pulledData.add(e);
+    }
+
     private void pullSystemUpTime(int tagId, List<StatsLogEventWrapper> pulledData) {
         StatsLogEventWrapper e = new StatsLogEventWrapper(SystemClock.elapsedRealtimeNanos(), tagId, 1);
         e.writeLong(SystemClock.uptimeMillis());
@@ -944,183 +942,6 @@
         }
     }
 
-    private void pullDiskStats(int tagId, List<StatsLogEventWrapper> pulledData) {
-        // Run a quick-and-dirty performance test: write 512 bytes
-        byte[] junk = new byte[512];
-        for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
-
-        File tmp = new File(Environment.getDataDirectory(), "system/statsdperftest.tmp");
-        FileOutputStream fos = null;
-        IOException error = null;
-
-        long before = SystemClock.elapsedRealtime();
-        try {
-            fos = new FileOutputStream(tmp);
-            fos.write(junk);
-        } catch (IOException e) {
-            error = e;
-        } finally {
-            try {
-                if (fos != null) fos.close();
-            } catch (IOException e) {
-                // Do nothing.
-            }
-        }
-
-        long latency = SystemClock.elapsedRealtime() - before;
-        if (tmp.exists()) tmp.delete();
-
-        if (error != null) {
-            Slog.e(TAG, "Error performing diskstats latency test");
-            latency = -1;
-        }
-        // File based encryption.
-        boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
-
-        //Recent disk write speed. Binder call to storaged.
-        int writeSpeed = -1;
-        try {
-            IBinder binder = ServiceManager.getService("storaged");
-            if (binder == null) {
-                Slog.e(TAG, "storaged not found");
-            }
-            IStoraged storaged = IStoraged.Stub.asInterface(binder);
-            writeSpeed = storaged.getRecentPerf();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "storaged not found");
-        }
-
-        // Add info pulledData.
-        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-        e.writeLong(latency);
-        e.writeBoolean(fileBased);
-        e.writeInt(writeSpeed);
-        pulledData.add(e);
-    }
-
-    private void pullDirectoryUsage(int tagId, List<StatsLogEventWrapper> pulledData) {
-        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
-        StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
-        StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
-
-        StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__DATA);
-        e.writeLong(statFsData.getAvailableBytes());
-        e.writeLong(statFsData.getTotalBytes());
-        pulledData.add(e);
-
-        e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__CACHE);
-        e.writeLong(statFsCache.getAvailableBytes());
-        e.writeLong(statFsCache.getTotalBytes());
-        pulledData.add(e);
-
-        e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-        e.writeInt(StatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM);
-        e.writeLong(statFsSystem.getAvailableBytes());
-        e.writeLong(statFsSystem.getTotalBytes());
-        pulledData.add(e);
-    }
-
-    private void pullAppSize(int tagId, List<StatsLogEventWrapper> pulledData) {
-        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        try {
-            String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
-            JSONObject json = new JSONObject(jsonStr);
-            long cache_time = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
-            JSONArray pkg_names = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
-            JSONArray app_sizes = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
-            JSONArray app_data_sizes = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY);
-            JSONArray app_cache_sizes = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
-            // Sanity check: Ensure all 4 lists have the same length.
-            int length = pkg_names.length();
-            if (app_sizes.length() != length || app_data_sizes.length() != length
-                    || app_cache_sizes.length() != length) {
-                Slog.e(TAG, "formatting error in diskstats cache file!");
-                return;
-            }
-            for (int i = 0; i < length; i++) {
-                StatsLogEventWrapper e =
-                        new StatsLogEventWrapper(elapsedNanos, tagId, 5 /* fields */);
-                e.writeString(pkg_names.getString(i));
-                e.writeLong(app_sizes.optLong(i, -1L));
-                e.writeLong(app_data_sizes.optLong(i, -1L));
-                e.writeLong(app_cache_sizes.optLong(i, -1L));
-                e.writeLong(cache_time);
-                pulledData.add(e);
-            }
-        } catch (IOException | JSONException e) {
-            Slog.e(TAG, "exception reading diskstats cache file", e);
-        }
-    }
-
-    private void pullCategorySize(int tagId, List<StatsLogEventWrapper> pulledData) {
-        long elapsedNanos = SystemClock.elapsedRealtimeNanos();
-        try {
-            String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
-            JSONObject json = new JSONObject(jsonStr);
-            long cacheTime = json.optLong(DiskStatsFileLogger.LAST_QUERY_TIMESTAMP_KEY, -1L);
-
-            StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_SIZE);
-            e.writeLong(json.optLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_DATA_SIZE);
-            e.writeLong(json.optLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__APP_CACHE_SIZE);
-            e.writeLong(json.optLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__PHOTOS);
-            e.writeLong(json.optLong(DiskStatsFileLogger.PHOTOS_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__VIDEOS);
-            e.writeLong(json.optLong(DiskStatsFileLogger.VIDEOS_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__AUDIO);
-            e.writeLong(json.optLong(DiskStatsFileLogger.AUDIO_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__DOWNLOADS);
-            e.writeLong(json.optLong(DiskStatsFileLogger.DOWNLOADS_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__SYSTEM);
-            e.writeLong(json.optLong(DiskStatsFileLogger.SYSTEM_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-
-            e = new StatsLogEventWrapper(elapsedNanos, tagId, 3 /* fields */);
-            e.writeInt(StatsLog.CATEGORY_SIZE__CATEGORY__OTHER);
-            e.writeLong(json.optLong(DiskStatsFileLogger.MISC_KEY, -1L));
-            e.writeLong(cacheTime);
-            pulledData.add(e);
-        } catch (IOException | JSONException e) {
-            Slog.e(TAG, "exception reading diskstats cache file", e);
-        }
-    }
-
     /**
      * Pulls various data.
      */
@@ -1195,6 +1016,10 @@
                 pullSystemElapsedRealtime(tagId, ret);
                 break;
             }
+            case StatsLog.DISK_SPACE: {
+                pullDiskSpace(tagId, ret);
+                break;
+            }
             case StatsLog.PROCESS_MEMORY_STATE: {
                 pullProcessMemoryState(tagId, ret);
                 break;
@@ -1207,22 +1032,6 @@
                 pullBinderCallsStatsExceptions(tagId, ret);
                 break;
             }
-            case StatsLog.DISK_STATS: {
-                pullDiskStats(tagId, ret);
-                break;
-            }
-            case StatsLog.DIRECTORY_USAGE: {
-                pullDirectoryUsage(tagId, ret);
-                break;
-            }
-            case StatsLog.APP_SIZE: {
-                pullAppSize(tagId, ret);
-                break;
-            }
-            case StatsLog.CATEGORY_SIZE: {
-                pullCategorySize(tagId, ret);
-                break;
-            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
index 7e57c9f4..9f77ed0 100644
--- a/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
+++ b/services/net/java/android/net/dhcp/DhcpLeaseRepository.java
@@ -29,7 +29,7 @@
 import android.net.IpPrefix;
 import android.net.MacAddress;
 import android.net.util.SharedLog;
-import android.os.SystemClock;
+import android.net.dhcp.DhcpServer.Clock;
 import android.util.ArrayMap;
 
 import java.net.Inet4Address;
@@ -73,15 +73,6 @@
     private int mNumAddresses;
     private long mLeaseTimeMs;
 
-    public static class Clock {
-        /**
-         * @see SystemClock#elapsedRealtime()
-         */
-        public long elapsedRealtime() {
-            return SystemClock.elapsedRealtime();
-        }
-    }
-
     /**
      * Next timestamp when committed or declined leases should be checked for expired ones. This
      * will always be lower than or equal to the time for the first lease to expire: it's OK not to
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 888821a..175e27e 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -9,6 +9,7 @@
 import android.os.SystemProperties;
 import android.system.OsConstants;
 import android.text.TextUtils;
+
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.UnsupportedEncodingException;
@@ -351,6 +352,14 @@
     }
 
     /**
+     * Convenience method to return the client ID if it was set explicitly, or null otherwise.
+     */
+    @Nullable
+    public byte[] getExplicitClientIdOrNull() {
+        return hasExplicitClientId() ? getClientId() : null;
+    }
+
+    /**
      * Returns the client ID. If not set explicitly, this follows RFC 2132 and creates a client ID
      * based on the hardware address.
      */
diff --git a/services/net/java/android/net/dhcp/DhcpPacketListener.java b/services/net/java/android/net/dhcp/DhcpPacketListener.java
index 498fd93..6f620c5 100644
--- a/services/net/java/android/net/dhcp/DhcpPacketListener.java
+++ b/services/net/java/android/net/dhcp/DhcpPacketListener.java
@@ -16,15 +16,14 @@
 
 package android.net.dhcp;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.util.FdEventsReader;
-import android.net.util.PacketReader;
 import android.os.Handler;
 import android.system.Os;
 
 import java.io.FileDescriptor;
 import java.net.Inet4Address;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 
 /**
@@ -35,19 +34,20 @@
     static final class Payload {
         final byte[] bytes = new byte[DhcpPacket.MAX_LENGTH];
         Inet4Address srcAddr;
+        int srcPort;
     }
 
-    public DhcpPacketListener(Handler handler) {
+    public DhcpPacketListener(@NonNull Handler handler) {
         super(handler, new Payload());
     }
 
     @Override
-    protected int recvBufSize(Payload buffer) {
+    protected int recvBufSize(@NonNull Payload buffer) {
         return buffer.bytes.length;
     }
 
     @Override
-    protected final void handlePacket(Payload recvbuf, int length) {
+    protected final void handlePacket(@NonNull Payload recvbuf, int length) {
         if (recvbuf.srcAddr == null) {
             return;
         }
@@ -55,30 +55,34 @@
         try {
             final DhcpPacket packet = DhcpPacket.decodeFullPacket(recvbuf.bytes, length,
                     DhcpPacket.ENCAP_BOOTP);
-            onReceive(packet, recvbuf.srcAddr);
+            onReceive(packet, recvbuf.srcAddr, recvbuf.srcPort);
         } catch (DhcpPacket.ParseException e) {
             logParseError(recvbuf.bytes, length, e);
         }
     }
 
     @Override
-    protected int readPacket(FileDescriptor fd, Payload packetBuffer) throws Exception {
+    protected int readPacket(@NonNull FileDescriptor fd, @NonNull Payload packetBuffer)
+            throws Exception {
         final InetSocketAddress addr = new InetSocketAddress();
         final int read = Os.recvfrom(
                 fd, packetBuffer.bytes, 0, packetBuffer.bytes.length, 0 /* flags */, addr);
 
         // Buffers with null srcAddr will be dropped in handlePacket()
         packetBuffer.srcAddr = inet4AddrOrNull(addr);
+        packetBuffer.srcPort = addr.getPort();
         return read;
     }
 
     @Nullable
-    private static Inet4Address inet4AddrOrNull(InetSocketAddress addr) {
+    private static Inet4Address inet4AddrOrNull(@NonNull InetSocketAddress addr) {
         return addr.getAddress() instanceof Inet4Address
                 ? (Inet4Address) addr.getAddress()
                 : null;
     }
 
-    protected abstract void onReceive(DhcpPacket packet, Inet4Address srcAddr);
-    protected abstract void logParseError(byte[] packet, int length, DhcpPacket.ParseException e);
+    protected abstract void onReceive(@NonNull DhcpPacket packet, @NonNull Inet4Address srcAddr,
+            int srcPort);
+    protected abstract void logParseError(@NonNull byte[] packet, int length,
+            @NonNull DhcpPacket.ParseException e);
 }
diff --git a/services/net/java/android/net/dhcp/DhcpServer.java b/services/net/java/android/net/dhcp/DhcpServer.java
new file mode 100644
index 0000000..095a5eb72
--- /dev/null
+++ b/services/net/java/android/net/dhcp/DhcpServer.java
@@ -0,0 +1,518 @@
+/*
+ * 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.dhcp;
+
+import static android.net.NetworkUtils.getBroadcastAddress;
+import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
+import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
+import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
+import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
+import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
+import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_BINDTODEVICE;
+import static android.system.OsConstants.SO_BROADCAST;
+import static android.system.OsConstants.SO_REUSEADDR;
+
+import static java.lang.Integer.toUnsignedLong;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.net.NetworkUtils;
+import android.net.TrafficStats;
+import android.net.util.InterfaceParams;
+import android.net.util.SharedLog;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.system.ErrnoException;
+import android.system.Os;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.HexDump;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+/**
+ * A DHCPv4 server.
+ *
+ * <p>This server listens for and responds to packets on a single interface. It considers itself
+ * authoritative for all leases on the subnet, which means that DHCP requests for unknown leases of
+ * unknown hosts receive a reply instead of being ignored.
+ *
+ * <p>The server is single-threaded (including send/receive operations): all internal operations are
+ * done on the provided {@link Looper}. Public methods are thread-safe and will schedule operations
+ * on the looper asynchronously.
+ * @hide
+ */
+public class DhcpServer {
+    private static final String REPO_TAG = "Repository";
+
+    // Lease time to transmit to client instead of a negative time in case a lease expired before
+    // the server could send it (if the server process is suspended for example).
+    private static final int EXPIRED_FALLBACK_LEASE_TIME_SECS = 120;
+
+    private static final int CMD_START_DHCP_SERVER = 1;
+    private static final int CMD_STOP_DHCP_SERVER = 2;
+    private static final int CMD_UPDATE_PARAMS = 3;
+
+    @NonNull
+    private final ServerHandler mHandler;
+    @NonNull
+    private final InterfaceParams mIface;
+    @NonNull
+    private final DhcpLeaseRepository mLeaseRepo;
+    @NonNull
+    private final SharedLog mLog;
+    @NonNull
+    private final Dependencies mDeps;
+    @NonNull
+    private final Clock mClock;
+    @NonNull
+    private final DhcpPacketListener mPacketListener;
+
+    @Nullable
+    private FileDescriptor mSocket;
+    @NonNull
+    private DhcpServingParams mServingParams;
+
+    public static class Clock {
+        /**
+         * @see SystemClock#elapsedRealtime()
+         */
+        public long elapsedRealtime() {
+            return SystemClock.elapsedRealtime();
+        }
+    }
+
+    public interface Dependencies {
+        void sendPacket(@NonNull FileDescriptor fd, @NonNull ByteBuffer buffer,
+                @NonNull InetAddress dst) throws ErrnoException, IOException;
+        DhcpLeaseRepository makeLeaseRepository(@NonNull DhcpServingParams servingParams,
+                @NonNull SharedLog log, @NonNull Clock clock);
+        DhcpPacketListener makePacketListener();
+        Clock makeClock();
+        void addArpEntry(@NonNull Inet4Address ipv4Addr, @NonNull MacAddress ethAddr,
+                @NonNull String ifname, @NonNull FileDescriptor fd) throws IOException;
+    }
+
+    private class DependenciesImpl implements Dependencies {
+        @Override
+        public void sendPacket(@NonNull FileDescriptor fd, @NonNull ByteBuffer buffer,
+                @NonNull InetAddress dst) throws ErrnoException, IOException {
+            Os.sendto(fd, buffer, 0, dst, DhcpPacket.DHCP_CLIENT);
+        }
+
+        @Override
+        public DhcpLeaseRepository makeLeaseRepository(@NonNull DhcpServingParams servingParams,
+                @NonNull SharedLog log, @NonNull Clock clock) {
+            return new DhcpLeaseRepository(
+                    DhcpServingParams.makeIpPrefix(servingParams.serverAddr),
+                    servingParams.excludedAddrs,
+                    servingParams.dhcpLeaseTimeSecs*1000, log.forSubComponent(REPO_TAG), clock);
+        }
+
+        @Override
+        public DhcpPacketListener makePacketListener() {
+            return new PacketListener();
+        }
+
+        @Override
+        public Clock makeClock() {
+            return new Clock();
+        }
+
+        @Override
+        public void addArpEntry(@NonNull Inet4Address ipv4Addr, @NonNull MacAddress ethAddr,
+                @NonNull String ifname, @NonNull FileDescriptor fd) throws IOException {
+            NetworkUtils.addArpEntry(ipv4Addr, ethAddr, ifname, fd);
+        }
+    }
+
+    private static class MalformedPacketException extends Exception {
+        MalformedPacketException(String message, Throwable t) {
+            super(message, t);
+        }
+    }
+
+    public DhcpServer(@NonNull Looper looper, @NonNull InterfaceParams iface,
+            @NonNull DhcpServingParams params, @NonNull SharedLog log) {
+        this(looper, iface, params, log, null);
+    }
+
+    @VisibleForTesting
+    DhcpServer(@NonNull Looper looper, @NonNull InterfaceParams iface,
+            @NonNull DhcpServingParams params, @NonNull SharedLog log,
+            @Nullable Dependencies deps) {
+        if (deps == null) {
+            deps = new DependenciesImpl();
+        }
+        mHandler = new ServerHandler(looper);
+        mIface = iface;
+        mServingParams = params;
+        mLog = log;
+        mDeps = deps;
+        mClock = deps.makeClock();
+        mPacketListener = deps.makePacketListener();
+        mLeaseRepo = deps.makeLeaseRepository(mServingParams, mLog, mClock);
+    }
+
+    /**
+     * Start listening for and responding to packets.
+     */
+    public void start() {
+        mHandler.sendEmptyMessage(CMD_START_DHCP_SERVER);
+    }
+
+    /**
+     * Update serving parameters. All subsequently received requests will be handled with the new
+     * parameters, and current leases that are incompatible with the new parameters are dropped.
+     */
+    public void updateParams(@NonNull DhcpServingParams params) {
+        sendMessage(CMD_UPDATE_PARAMS, params);
+    }
+
+    /**
+     * Stop listening for packets.
+     *
+     * <p>As the server is stopped asynchronously, some packets may still be processed shortly after
+     * calling this method.
+     */
+    public void stop() {
+        mHandler.sendEmptyMessage(CMD_STOP_DHCP_SERVER);
+    }
+
+    private void sendMessage(int what, @Nullable Object obj) {
+        mHandler.sendMessage(mHandler.obtainMessage(what, obj));
+    }
+
+    private class ServerHandler extends Handler {
+        public ServerHandler(@NonNull Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(@NonNull Message msg) {
+            switch (msg.what) {
+                case CMD_UPDATE_PARAMS:
+                    final DhcpServingParams params = (DhcpServingParams) msg.obj;
+                    mServingParams = params;
+                    mLeaseRepo.updateParams(
+                            DhcpServingParams.makeIpPrefix(mServingParams.serverAddr),
+                            params.excludedAddrs,
+                            params.dhcpLeaseTimeSecs);
+                    break;
+                case CMD_START_DHCP_SERVER:
+                    // This is a no-op if the listener is already started
+                    mPacketListener.start();
+                    break;
+                case CMD_STOP_DHCP_SERVER:
+                    // This is a no-op if the listener was not started
+                    mPacketListener.stop();
+                    break;
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void processPacket(@NonNull DhcpPacket packet, int srcPort) {
+        final String packetType = packet.getClass().getSimpleName();
+        if (srcPort != DHCP_CLIENT) {
+            mLog.logf("Ignored packet of type %s sent from client port %d", packetType, srcPort);
+            return;
+        }
+
+        mLog.log("Received packet of type " + packetType);
+        final Inet4Address sid = packet.mServerIdentifier;
+        if (sid != null && !sid.equals(mServingParams.serverAddr.getAddress())) {
+            mLog.log("Packet ignored due to wrong server identifier: " + sid);
+            return;
+        }
+
+        try {
+            if (packet instanceof DhcpDiscoverPacket) {
+                processDiscover((DhcpDiscoverPacket) packet);
+            } else if (packet instanceof DhcpRequestPacket) {
+                processRequest((DhcpRequestPacket) packet);
+            } else if (packet instanceof DhcpReleasePacket) {
+                processRelease((DhcpReleasePacket) packet);
+            } else {
+                mLog.e("Unknown packet type: " + packet.getClass().getSimpleName());
+            }
+        } catch (MalformedPacketException e) {
+            // Not an internal error: only logging exception message, not stacktrace
+            mLog.e("Ignored malformed packet: " + e.getMessage());
+        }
+    }
+
+    private void processDiscover(@NonNull DhcpDiscoverPacket packet)
+            throws MalformedPacketException {
+        final DhcpLease lease;
+        final MacAddress clientMac = getMacAddr(packet);
+        try {
+            lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac,
+                    packet.mRelayIp, packet.mRequestedIp, packet.mHostName);
+        } catch (DhcpLeaseRepository.OutOfAddressesException e) {
+            transmitNak(packet, "Out of addresses to offer");
+            return;
+        } catch (DhcpLeaseRepository.InvalidAddressException e) {
+            transmitNak(packet, "Lease requested from an invalid subnet");
+            return;
+        }
+
+        transmitOffer(packet, lease, clientMac);
+    }
+
+    private void processRequest(@NonNull DhcpRequestPacket packet) throws MalformedPacketException {
+        // If set, packet SID matches with this server's ID as checked in processPacket().
+        final boolean sidSet = packet.mServerIdentifier != null;
+        final DhcpLease lease;
+        final MacAddress clientMac = getMacAddr(packet);
+        try {
+            lease = mLeaseRepo.requestLease(packet.getExplicitClientIdOrNull(), clientMac,
+                    packet.mClientIp, packet.mRequestedIp, sidSet, packet.mHostName);
+        } catch (DhcpLeaseRepository.InvalidAddressException e) {
+            transmitNak(packet, "Invalid requested address");
+            return;
+        }
+
+        transmitAck(packet, lease, clientMac);
+    }
+
+    private void processRelease(@Nullable DhcpReleasePacket packet)
+            throws MalformedPacketException {
+        final byte[] clientId = packet.getExplicitClientIdOrNull();
+        final MacAddress macAddr = getMacAddr(packet);
+        // Don't care about success (there is no ACK/NAK); logging is already done in the repository
+        mLeaseRepo.releaseLease(clientId, macAddr, packet.mClientIp);
+    }
+
+    private Inet4Address getAckOrOfferDst(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
+            boolean broadcastFlag) {
+        // Unless relayed or broadcast, send to client IP if already configured on the client, or to
+        // the lease address if the client has no configured address
+        if (!isEmpty(request.mRelayIp)) {
+            return request.mRelayIp;
+        } else if (broadcastFlag) {
+            return (Inet4Address) Inet4Address.ALL;
+        } else if (!isEmpty(request.mClientIp)) {
+            return request.mClientIp;
+        } else {
+            return lease.getNetAddr();
+        }
+    }
+
+    /**
+     * Determine whether the broadcast flag should be set in the BOOTP packet flags. This does not
+     * apply to NAK responses, which should always have it set.
+     */
+    private static boolean getBroadcastFlag(@NonNull DhcpPacket request, @NonNull DhcpLease lease) {
+        // No broadcast flag if the client already has a configured IP to unicast to. RFC2131 #4.1
+        // has some contradictions regarding broadcast behavior if a client already has an IP
+        // configured and sends a request with both ciaddr (renew/rebind) and the broadcast flag
+        // set. Sending a unicast response to ciaddr matches previous behavior and is more
+        // efficient.
+        // If the client has no configured IP, broadcast if requested by the client or if the lease
+        // address cannot be used to send a unicast reply either.
+        return isEmpty(request.mClientIp) && (request.mBroadcast || isEmpty(lease.getNetAddr()));
+    }
+
+    private boolean transmitOffer(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
+            @NonNull MacAddress clientMac) {
+        final boolean broadcastFlag = getBroadcastFlag(request, lease);
+        final int timeout = getLeaseTimeout(lease);
+        final Inet4Address prefixMask =
+                getPrefixMaskAsInet4Address(mServingParams.serverAddr.getPrefixLength());
+        final Inet4Address broadcastAddr = getBroadcastAddress(
+                mServingParams.getServerInet4Addr(), mServingParams.serverAddr.getPrefixLength());
+        final ByteBuffer offerPacket = DhcpPacket.buildOfferPacket(
+                ENCAP_BOOTP, request.mTransId, broadcastFlag, mServingParams.getServerInet4Addr(),
+                lease.getNetAddr(), request.mClientMac, timeout,
+                prefixMask,
+                broadcastAddr,
+                new ArrayList<>(mServingParams.defaultRouters),
+                new ArrayList<>(mServingParams.dnsServers),
+                mServingParams.getServerInet4Addr(), null /* domainName */);
+
+        return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag);
+    }
+
+    private boolean transmitAck(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
+            @NonNull MacAddress clientMac) {
+        // TODO: replace DhcpPacket's build methods with real builders and use common code with
+        // transmitOffer above
+        final boolean broadcastFlag = getBroadcastFlag(request, lease);
+        final int timeout = getLeaseTimeout(lease);
+        final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId,
+                broadcastFlag, mServingParams.getServerInet4Addr(), lease.getNetAddr(),
+                request.mClientMac, timeout, mServingParams.getPrefixMaskAsAddress(),
+                mServingParams.getBroadcastAddress(),
+                new ArrayList<>(mServingParams.defaultRouters),
+                new ArrayList<>(mServingParams.dnsServers),
+                mServingParams.getServerInet4Addr(), null /* domainName */);
+
+        return transmitOfferOrAckPacket(ackPacket, request, lease, clientMac, broadcastFlag);
+    }
+
+    private boolean transmitNak(DhcpPacket request, String message) {
+        mLog.w("Transmitting NAK: " + message);
+        // Always set broadcast flag for NAK: client may not have a correct IP
+        final ByteBuffer nakPacket = DhcpPacket.buildNakPacket(
+                ENCAP_BOOTP, request.mTransId, mServingParams.getServerInet4Addr(),
+                request.mClientMac, true /* broadcast */, message);
+
+        final Inet4Address dst = isEmpty(request.mRelayIp)
+                ? (Inet4Address) Inet4Address.ALL
+                : request.mRelayIp;
+        return transmitPacket(nakPacket, DhcpNakPacket.class.getSimpleName(), dst);
+    }
+
+    private boolean transmitOfferOrAckPacket(@NonNull ByteBuffer buf, @NonNull DhcpPacket request,
+            @NonNull DhcpLease lease, @NonNull MacAddress clientMac, boolean broadcastFlag) {
+        mLog.logf("Transmitting %s with lease %s", request.getClass().getSimpleName(), lease);
+        // Client may not yet respond to ARP for the lease address, which may be the destination
+        // address. Add an entry to the ARP cache to save future ARP probes and make sure the
+        // packet reaches its destination.
+        if (!addArpEntry(clientMac, lease.getNetAddr())) {
+            // Logging for error already done
+            return false;
+        }
+        final Inet4Address dst = getAckOrOfferDst(request, lease, broadcastFlag);
+        return transmitPacket(buf, request.getClass().getSimpleName(), dst);
+    }
+
+    private boolean transmitPacket(@NonNull ByteBuffer buf, @NonNull String packetTypeTag,
+            @NonNull Inet4Address dst) {
+        try {
+            mDeps.sendPacket(mSocket, buf, dst);
+        } catch (ErrnoException | IOException e) {
+            mLog.e("Can't send packet " + packetTypeTag, e);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean addArpEntry(@NonNull MacAddress macAddr, @NonNull Inet4Address inetAddr) {
+        try {
+            mDeps.addArpEntry(inetAddr, macAddr, mIface.name, mSocket);
+            return true;
+        } catch (IOException e) {
+            mLog.e("Error adding client to ARP table", e);
+            return false;
+        }
+    }
+
+    /**
+     * Get the remaining lease time in seconds, starting from {@link Clock#elapsedRealtime()}.
+     *
+     * <p>This is an unsigned 32-bit integer, so it cannot be read as a standard (signed) Java int.
+     * The return value is only intended to be used to populate the lease time field in a DHCP
+     * response, considering that lease time is an unsigned 32-bit integer field in DHCP packets.
+     *
+     * <p>Lease expiration times are tracked internally with millisecond precision: this method
+     * returns a rounded down value.
+     */
+    private int getLeaseTimeout(@NonNull DhcpLease lease) {
+        final long remainingTimeSecs = (lease.getExpTime() - mClock.elapsedRealtime()) / 1000;
+        if (remainingTimeSecs < 0) {
+            mLog.e("Processing expired lease " + lease);
+            return EXPIRED_FALLBACK_LEASE_TIME_SECS;
+        }
+
+        if (remainingTimeSecs >= toUnsignedLong(INFINITE_LEASE)) {
+            return INFINITE_LEASE;
+        }
+
+        return (int) remainingTimeSecs;
+    }
+
+    /**
+     * Get the client MAC address from a packet.
+     *
+     * @throws MalformedPacketException The address in the packet uses an unsupported format.
+     */
+    @NonNull
+    private MacAddress getMacAddr(@NonNull DhcpPacket packet) throws MalformedPacketException {
+        try {
+            return MacAddress.fromBytes(packet.getClientMac());
+        } catch (IllegalArgumentException e) {
+            final String message = "Invalid MAC address in packet: "
+                    + HexDump.dumpHexString(packet.getClientMac());
+            throw new MalformedPacketException(message, e);
+        }
+    }
+
+    private static boolean isEmpty(@NonNull Inet4Address address) {
+        return address == null || Inet4Address.ANY.equals(address);
+    }
+
+    private class PacketListener extends DhcpPacketListener {
+        public PacketListener() {
+            super(mHandler);
+        }
+
+        @Override
+        protected void onReceive(DhcpPacket packet, Inet4Address srcAddr, int srcPort) {
+            processPacket(packet, srcPort);
+        }
+
+        @Override
+        protected void logError(String msg, Exception e) {
+            mLog.e("Error receiving packet: " + msg, e);
+        }
+
+        @Override
+        protected void logParseError(byte[] packet, int length, DhcpPacket.ParseException e) {
+            mLog.e("Error parsing packet", e);
+        }
+
+        @Override
+        protected FileDescriptor createFd() {
+            // TODO: have and use an API to set a socket tag without going through the thread tag
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TAG_SYSTEM_DHCP_SERVER);
+            try {
+                mSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+                Os.setsockoptInt(mSocket, SOL_SOCKET, SO_REUSEADDR, 1);
+                // SO_BINDTODEVICE actually takes a string. This works because the first member
+                // of struct ifreq is a NULL-terminated interface name.
+                // TODO: add a setsockoptString()
+                Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIface.name);
+                Os.setsockoptInt(mSocket, SOL_SOCKET, SO_BROADCAST, 1);
+                Os.bind(mSocket, Inet4Address.ANY, DHCP_SERVER);
+                NetworkUtils.protectFromVpn(mSocket);
+
+                return mSocket;
+            } catch (IOException | ErrnoException e) {
+                mLog.e("Error creating UDP socket", e);
+                DhcpServer.this.stop();
+                return null;
+            } finally {
+                TrafficStats.setThreadStatsTag(oldTag);
+            }
+        }
+    }
+}
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index b77da28..3cdef1e 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -431,6 +431,7 @@
         public ProvisioningConfiguration(ProvisioningConfiguration other) {
             mEnableIPv4 = other.mEnableIPv4;
             mEnableIPv6 = other.mEnableIPv6;
+            mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker;
             mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor;
             mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs;
             mInitialConfig = InitialConfiguration.copy(other.mInitialConfig);
diff --git a/services/net/java/android/net/util/FdEventsReader.java b/services/net/java/android/net/util/FdEventsReader.java
index 575444f..8bbf449 100644
--- a/services/net/java/android/net/util/FdEventsReader.java
+++ b/services/net/java/android/net/util/FdEventsReader.java
@@ -89,7 +89,7 @@
         mBuffer = buffer;
     }
 
-    public final void start() {
+    public void start() {
         if (onCorrectThread()) {
             createAndRegisterFd();
         } else {
@@ -100,7 +100,7 @@
         }
     }
 
-    public final void stop() {
+    public void stop() {
         if (onCorrectThread()) {
             unregisterAndDestroyFd();
         } else {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 97068a6..0cf1aec 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1994,18 +1994,25 @@
      * the binding intent go to.
      * @hide
      */
-    public static final String KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING
-             = "carrier_network_service_wlan_package_override_string";
+    public static final String KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING =
+            "carrier_network_service_wlan_package_override_string";
 
     /**
      * Decides when clients try to bind to wwan (cellular) network service, which package name will
      * the binding intent go to.
      * @hide
      */
-    public static final String KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
-            = "carrier_network_service_wwan_package_override_string";
+    public static final String KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING =
+            "carrier_network_service_wwan_package_override_string";
 
     /**
+     * The package name of qualified networks service that telephony binds to.
+     *
+     * @hide
+     */
+    public static final String KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING =
+            "carrier_qualified_networks_service_package_override_string";
+    /**
      * A list of 4 LTE RSCP thresholds above which a signal level is considered POOR,
      * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
      *
@@ -2094,6 +2101,7 @@
         sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
         sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
+        sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
         sDefaults.putString(KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING, "");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 82e3a9d..dab62f1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2843,9 +2843,11 @@
     }
 
     /**
-     * Return if the current radio is LTE on CDMA. This
-     * is a tri-state return value as for a period of time
-     * the mode may be unknown.
+     * Return if the current radio is LTE on CDMA. This is a tri-state return value as for a period
+     * of time the mode may be unknown.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
      * @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
      * or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
@@ -5630,6 +5632,9 @@
     /**
      * Sets the network selection mode to automatic.
      *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -5652,27 +5657,36 @@
     /**
      * Perform a radio scan and return the list of available networks.
      *
-     * The return value is a list of the OperatorInfo of the networks found. Note that this
-     * scan can take a long time (sometimes minutes) to happen.
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * <p> Note that this scan can take a long time (sometimes minutes) to happen.
      *
      * <p>Requires Permission:
-     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
-     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges})
+     *
+     * @return {@link CellNetworkScanResult} with the status
+     * {@link CellNetworkScanResult#STATUS_SUCCESS} and a list of
+     * {@link com.android.internal.telephony.OperatorInfo} if it's available. Otherwise, the failure
+     * caused will be included in the result.
      *
      * @hide
-     * TODO: Add an overload that takes no args.
      */
-    public CellNetworkScanResult getCellNetworkScanResults(int subId) {
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public CellNetworkScanResult getAvailableNetworks() {
         try {
             ITelephony telephony = getITelephony();
-            if (telephony != null)
-                return telephony.getCellNetworkScanResults(subId);
+            if (telephony != null) {
+                return telephony.getCellNetworkScanResults(getSubId());
+            }
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "getCellNetworkScanResults RemoteException", ex);
+            Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
         } catch (NullPointerException ex) {
-            Rlog.e(TAG, "getCellNetworkScanResults NPE", ex);
+            Rlog.e(TAG, "getAvailableNetworks NPE", ex);
         }
-        return null;
+        return new CellNetworkScanResult(
+                CellNetworkScanResult.STATUS_UNKNOWN_ERROR, null /* OperatorInfo */);
     }
 
     /**
@@ -5722,6 +5736,9 @@
     /**
      * Ask the radio to connect to the input network and change selection mode to manual.
      *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
      * app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -7474,6 +7491,9 @@
     /**
      * Returns the current {@link ServiceState} information.
      *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
@@ -7941,8 +7961,12 @@
     }
 
     /**
-     * Check if phone is in emergency callback mode
-     * @return true if phone is in emergency callback mode
+     * Checks if phone is in emergency callback mode.
+     *
+     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
+     * @return true if phone is in emergency callback mode.
      * @hide
      */
     @SystemApi
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index f646028b4..0abe45c 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
@@ -83,7 +84,9 @@
      * field here, NOT name.  We're NOT always guaranteed to have a name
      * for a connection, but the number should be displayable.
      */
+    @UnsupportedAppUsage
     public String name;
+    @UnsupportedAppUsage
     public String phoneNumber;
     public String normalizedNumber;
     public String geoDescription;
@@ -95,12 +98,15 @@
 
     public String phoneLabel;
     /* Split up the phoneLabel into number type and label name */
+    @UnsupportedAppUsage
     public int    numberType;
+    @UnsupportedAppUsage
     public String numberLabel;
 
     public int photoResource;
 
     // Contact ID, which will be 0 if a contact comes from the corp CP2.
+    @UnsupportedAppUsage
     public long contactIdOrZero;
     public boolean needUpdate;
     public Uri contactRefUri;
@@ -155,6 +161,7 @@
     private boolean mIsEmergency;
     private boolean mIsVoiceMail;
 
+    @UnsupportedAppUsage
     public CallerInfo() {
         // TODO: Move all the basic initialization here?
         mIsEmergency = false;
@@ -300,6 +307,7 @@
      * @return the CallerInfo which contains the caller id for the given
      * number. The returned CallerInfo is null if no number is supplied.
      */
+    @UnsupportedAppUsage
     public static CallerInfo getCallerInfo(Context context, Uri contactRef) {
         CallerInfo info = null;
         ContentResolver cr = CallerInfoAsyncQuery.getCurrentProfileContentResolver(context);
@@ -324,6 +332,7 @@
      * a matching number is not found, then a generic caller info is returned,
      * with all relevant fields empty or null.
      */
+    @UnsupportedAppUsage
     public static CallerInfo getCallerInfo(Context context, String number) {
         if (VDBG) Rlog.v(TAG, "getCallerInfo() based on number...");
 
@@ -342,6 +351,7 @@
      * a matching number is not found, then a generic caller info is returned,
      * with all relevant fields empty or null.
      */
+    @UnsupportedAppUsage
     public static CallerInfo getCallerInfo(Context context, String number, int subId) {
 
         if (TextUtils.isEmpty(number)) {
diff --git a/telephony/java/com/android/internal/telephony/EncodeException.java b/telephony/java/com/android/internal/telephony/EncodeException.java
index 0436ba0..4e3fac1 100644
--- a/telephony/java/com/android/internal/telephony/EncodeException.java
+++ b/telephony/java/com/android/internal/telephony/EncodeException.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * {@hide}
  */
@@ -24,10 +26,12 @@
         super();
     }
 
+    @UnsupportedAppUsage
     public EncodeException(String s) {
         super(s);
     }
 
+    @UnsupportedAppUsage
     public EncodeException(char c) {
         super("Unencodable char: '" + c + "'");
     }
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 4785169..69ff329 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -20,6 +20,7 @@
 import android.text.TextUtils;
 import android.util.SparseIntArray;
 
+import android.annotation.UnsupportedAppUsage;
 import android.telephony.Rlog;
 
 import java.nio.ByteBuffer;
@@ -84,6 +85,7 @@
         /**
          *The number of SMS's required to encode the text.
          */
+        @UnsupportedAppUsage
         public int msgCount;
 
         /**
@@ -92,28 +94,33 @@
          * septets for the standard ASCII and GSM encodings, and 16
          * bits for Unicode.
          */
+        @UnsupportedAppUsage
         public int codeUnitCount;
 
         /**
          * How many code units are still available without spilling
          * into an additional message.
          */
+        @UnsupportedAppUsage
         public int codeUnitsRemaining;
 
         /**
          * The encoding code unit size (specified using
          * android.telephony.SmsMessage ENCODING_*).
          */
+        @UnsupportedAppUsage
         public int codeUnitSize;
 
         /**
          * The GSM national language table to use, or 0 for the default 7-bit alphabet.
          */
+        @UnsupportedAppUsage
         public int languageTable;
 
         /**
          * The GSM national language shift table to use, or 0 for the default 7-bit extension table.
          */
+        @UnsupportedAppUsage
         public int languageShiftTable;
 
         @Override
@@ -138,6 +145,7 @@
      * @param c the character to convert
      * @return the GSM 7 bit table index for the specified character
      */
+    @UnsupportedAppUsage
     public static int
     charToGsm(char c) {
         try {
@@ -160,6 +168,7 @@
      * @throws EncodeException encode error when throwException is true
      * @return the GSM 7 bit table index for the specified character
      */
+    @UnsupportedAppUsage
     public static int
     charToGsm(char c, boolean throwException) throws EncodeException {
         int ret;
@@ -215,6 +224,7 @@
      * @param gsmChar the GSM 7 bit table index to convert
      * @return the decoded character
      */
+    @UnsupportedAppUsage
     public static char
     gsmToChar(int gsmChar) {
         if (gsmChar >= 0 && gsmChar < 128) {
@@ -293,6 +303,7 @@
      * @return Byte array containing header and encoded data.
      * @throws EncodeException if String is too large to encode
      */
+    @UnsupportedAppUsage
     public static byte[] stringToGsm7BitPackedWithHeader(String data, byte[] header,
             int languageTable, int languageShiftTable)
             throws EncodeException {
@@ -327,6 +338,7 @@
      * @return the encoded string
      * @throws EncodeException if String is too large to encode
      */
+    @UnsupportedAppUsage
     public static byte[] stringToGsm7BitPacked(String data)
             throws EncodeException {
         return stringToGsm7BitPacked(data, 0, true, 0, 0);
@@ -377,6 +389,7 @@
      *
      * @throws EncodeException if String is too large to encode
      */
+    @UnsupportedAppUsage
     public static byte[] stringToGsm7BitPacked(String data, int startingSeptetOffset,
             boolean throwException, int languageTable, int languageShiftTable)
             throws EncodeException {
@@ -428,6 +441,7 @@
      *                  (septet index * 7)
      * @param value the 7-bit character to store
      */
+    @UnsupportedAppUsage
     private static void
     packSmsChar(byte[] packedChars, int bitOffset, int value) {
         int byteOffset = bitOffset / 8;
@@ -451,6 +465,7 @@
      * @param lengthSeptets string length in septets, not bytes
      * @return String representation or null on decoding exception
      */
+    @UnsupportedAppUsage
     public static String gsm7BitPackedToString(byte[] pdu, int offset,
             int lengthSeptets) {
         return gsm7BitPackedToString(pdu, offset, lengthSeptets, 0, 0, 0);
@@ -472,6 +487,7 @@
      *     GSM extension table
      * @return String representation or null on decoding exception
      */
+    @UnsupportedAppUsage
     public static String gsm7BitPackedToString(byte[] pdu, int offset,
             int lengthSeptets, int numPaddingBits, int languageTable, int shiftTable) {
         StringBuilder ret = new StringBuilder(lengthSeptets);
@@ -555,6 +571,7 @@
      * @param length the number of bytes to decode
      * @return the decoded string
      */
+    @UnsupportedAppUsage
     public static String
     gsm8BitUnpackedToString(byte[] data, int offset, int length) {
         return gsm8BitUnpackedToString(data, offset, length, "");
@@ -570,6 +587,7 @@
      * Additionally, in some country(ex. Korea), there are non-ASCII or MBCS characters.
      * If a character set is given, characters in data are treat as MBCS.
      */
+    @UnsupportedAppUsage
     public static String
     gsm8BitUnpackedToString(byte[] data, int offset, int length, String characterset) {
         boolean isMbcs = false;
@@ -649,6 +667,7 @@
      * @param s the string to encode
      * @return the 8-bit GSM encoded byte array for the string
      */
+    @UnsupportedAppUsage
     public static byte[]
     stringToGsm8BitPacked(String s) {
         byte[] ret;
@@ -736,6 +755,7 @@
      * @return the number of septets for this character
      * @throws EncodeException the character can't be encoded and throwsException is true
      */
+    @UnsupportedAppUsage
     public static int
     countGsmSeptets(char c, boolean throwsException) throws EncodeException {
         if (sCharsToGsmTables[0].get(c, -1) != -1) {
@@ -978,6 +998,7 @@
      * @return index of first character that won't fit, or the length
      *   of the entire string if everything fits
      */
+    @UnsupportedAppUsage
     public static int
     findGsmSeptetLimitIndex(String s, int start, int limit, int langTable, int langShiftTable) {
         int accumulator = 0;
@@ -1076,18 +1097,23 @@
     }
 
     /** Reverse mapping from Unicode characters to indexes into language tables. */
+    @UnsupportedAppUsage
     private static final SparseIntArray[] sCharsToGsmTables;
 
     /** Reverse mapping from Unicode characters to indexes into language shift tables. */
+    @UnsupportedAppUsage
     private static final SparseIntArray[] sCharsToShiftTables;
 
     /** OEM configured list of enabled national language single shift tables for encoding. */
+    @UnsupportedAppUsage
     private static int[] sEnabledSingleShiftTables;
 
     /** OEM configured list of enabled national language locking shift tables for encoding. */
+    @UnsupportedAppUsage
     private static int[] sEnabledLockingShiftTables;
 
     /** Highest language code to include in array of single shift counters. */
+    @UnsupportedAppUsage
     private static int sHighestEnabledSingleShiftCode;
 
     /** Flag to bypass check for country-specific overlays (for test cases only). */
@@ -1098,9 +1124,13 @@
      * the single shift tables that it can be paired with.
      */
     private static class LanguagePairCount {
+        @UnsupportedAppUsage
         final int languageCode;
+        @UnsupportedAppUsage
         final int[] septetCounts;
+        @UnsupportedAppUsage
         final int[] unencodableCounts;
+        @UnsupportedAppUsage
         LanguagePairCount(int code) {
             this.languageCode = code;
             int maxSingleShiftCode = sHighestEnabledSingleShiftCode;
@@ -1130,6 +1160,7 @@
      * GSM default 7 bit alphabet plus national language locking shift character tables.
      * Comment lines above strings indicate the lower four bits of the table position.
      */
+    @UnsupportedAppUsage
     private static final String[] sLanguageTables = {
         /* 3GPP TS 23.038 V9.1.1 section 6.2.1 - GSM 7 bit Default Alphabet
          01.....23.....4.....5.....6.....7.....8.....9.....A.B.....C.....D.E.....F.....0.....1 */
@@ -1323,6 +1354,7 @@
     /**
      * GSM default extension table plus national language single shift character tables.
      */
+    @UnsupportedAppUsage
     private static final String[] sLanguageShiftTables = new String[]{
         /* 6.2.1.1 GSM 7 bit Default Alphabet Extension Table
          0123456789A.....BCDEF0123456789ABCDEF0123456789ABCDEF.0123456789ABCDEF0123456789ABCDEF */
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index a29d7c1..d0245a0 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,37 +27,48 @@
     public enum State {
         UNKNOWN,
         AVAILABLE,
+        @UnsupportedAppUsage
         CURRENT,
+        @UnsupportedAppUsage
         FORBIDDEN;
     }
 
+    @UnsupportedAppUsage
     private String mOperatorAlphaLong;
+    @UnsupportedAppUsage
     private String mOperatorAlphaShort;
+    @UnsupportedAppUsage
     private String mOperatorNumeric;
 
+    @UnsupportedAppUsage
     private State mState = State.UNKNOWN;
 
 
+    @UnsupportedAppUsage
     public String
     getOperatorAlphaLong() {
         return mOperatorAlphaLong;
     }
 
+    @UnsupportedAppUsage
     public String
     getOperatorAlphaShort() {
         return mOperatorAlphaShort;
     }
 
+    @UnsupportedAppUsage
     public String
     getOperatorNumeric() {
         return mOperatorNumeric;
     }
 
+    @UnsupportedAppUsage
     public State
     getState() {
         return mState;
     }
 
+    @UnsupportedAppUsage
     OperatorInfo(String operatorAlphaLong,
                 String operatorAlphaShort,
                 String operatorNumeric,
@@ -70,6 +82,7 @@
     }
 
 
+    @UnsupportedAppUsage
     public OperatorInfo(String operatorAlphaLong,
                 String operatorAlphaShort,
                 String operatorNumeric,
@@ -78,6 +91,7 @@
                 operatorNumeric, rilStateToState(stateString));
     }
 
+    @UnsupportedAppUsage
     public OperatorInfo(String operatorAlphaLong,
             String operatorAlphaShort,
             String operatorNumeric) {
@@ -87,6 +101,7 @@
     /**
      * See state strings defined in ril.h RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
      */
+    @UnsupportedAppUsage
     private static State rilStateToState(String s) {
         if (s.equals("unknown")) {
             return State.UNKNOWN;
@@ -140,6 +155,7 @@
      * Implement the Parcelable interface
      * Method to deserialize a OperatorInfo object, or an array thereof.
      */
+    @UnsupportedAppUsage
     public static final Creator<OperatorInfo> CREATOR =
         new Creator<OperatorInfo>() {
             @Override
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
index b3892cb..2a8de8c 100644
--- a/telephony/java/com/android/internal/telephony/SmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
+
 public abstract class SmsAddress {
     // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
     // and C.S0005-D table 2.7.1.3.2.4-2
@@ -29,6 +31,7 @@
 
     public int ton;
     public String address;
+    @UnsupportedAppUsage
     public byte[] origBytes;
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/SmsConstants.java b/telephony/java/com/android/internal/telephony/SmsConstants.java
index 0aba468..19f52b0 100644
--- a/telephony/java/com/android/internal/telephony/SmsConstants.java
+++ b/telephony/java/com/android/internal/telephony/SmsConstants.java
@@ -15,6 +15,8 @@
  */
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
+
 /**
  * SMS Constants and must be the same as the corresponding
  * deprecated version in SmsMessage.
@@ -58,10 +60,15 @@
      * See TS 23.038.
      */
     public enum MessageClass{
+        @UnsupportedAppUsage
         UNKNOWN,
+        @UnsupportedAppUsage
         CLASS_0,
+        @UnsupportedAppUsage
         CLASS_1,
+        @UnsupportedAppUsage
         CLASS_2,
+        @UnsupportedAppUsage
         CLASS_3;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
index b519b70..9fe1718 100644
--- a/telephony/java/com/android/internal/telephony/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -22,6 +22,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 
 /**
@@ -72,14 +73,19 @@
     public static final int PORT_WAP_WSP  = 9200;
 
     public static class PortAddrs {
+        @UnsupportedAppUsage
         public int destPort;
+        @UnsupportedAppUsage
         public int origPort;
         public boolean areEightBits;
     }
 
     public static class ConcatRef {
+        @UnsupportedAppUsage
         public int refNumber;
+        @UnsupportedAppUsage
         public int seqNumber;
+        @UnsupportedAppUsage
         public int msgCount;
         public boolean isEightBits;
     }
@@ -98,17 +104,22 @@
         public byte[] data;
     }
 
+    @UnsupportedAppUsage
     public PortAddrs portAddrs;
+    @UnsupportedAppUsage
     public ConcatRef concatRef;
     public ArrayList<SpecialSmsMsg> specialSmsMsgList = new ArrayList<SpecialSmsMsg>();
     public ArrayList<MiscElt> miscEltList = new ArrayList<MiscElt>();
 
     /** 7 bit national language locking shift table, or 0 for GSM default 7 bit alphabet. */
+    @UnsupportedAppUsage
     public int languageTable;
 
     /** 7 bit national language single shift table, or 0 for GSM default 7 bit extension table. */
+    @UnsupportedAppUsage
     public int languageShiftTable;
 
+    @UnsupportedAppUsage
     public SmsHeader() {}
 
     /**
@@ -117,6 +128,7 @@
      * @param data is user data header bytes
      * @return SmsHeader object
      */
+    @UnsupportedAppUsage
     public static SmsHeader fromByteArray(byte[] data) {
         ByteArrayInputStream inStream = new ByteArrayInputStream(data);
         SmsHeader smsHeader = new SmsHeader();
@@ -198,6 +210,7 @@
      * (see TS 23.040 9.2.3.24)
      * @return Byte array representing the SmsHeader
      */
+    @UnsupportedAppUsage
     public static byte[] toByteArray(SmsHeader smsHeader) {
         if ((smsHeader.portAddrs == null) &&
             (smsHeader.concatRef == null) &&
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index e5821dc..7b1ead9 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -22,6 +22,7 @@
 import java.text.BreakIterator;
 import java.util.Arrays;
 
+import android.annotation.UnsupportedAppUsage;
 import android.provider.Telephony;
 import android.telephony.SmsMessage;
 import android.text.Emoji;
@@ -32,12 +33,15 @@
  */
 public abstract class SmsMessageBase {
     /** {@hide} The address of the SMSC. May be null */
+    @UnsupportedAppUsage
     protected String mScAddress;
 
     /** {@hide} The address of the sender */
+    @UnsupportedAppUsage
     protected SmsAddress mOriginatingAddress;
 
     /** {@hide} The message body as a string. May be null if the message isn't text */
+    @UnsupportedAppUsage
     protected String mMessageBody;
 
     /** {@hide} */
@@ -56,23 +60,28 @@
     protected long mScTimeMillis;
 
     /** {@hide} The raw PDU of the message */
+    @UnsupportedAppUsage
     protected byte[] mPdu;
 
     /** {@hide} The raw bytes for the user data section of the message */
     protected byte[] mUserData;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     protected SmsHeader mUserDataHeader;
 
     // "Message Waiting Indication Group"
     // 23.038 Section 4
     /** {@hide} */
+    @UnsupportedAppUsage
     protected boolean mIsMwi;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     protected boolean mMwiSense;
 
     /** {@hide} */
+    @UnsupportedAppUsage
     protected boolean mMwiDontStore;
 
     /**
@@ -86,11 +95,14 @@
     protected int mIndexOnIcc = -1;
 
     /** TP-Message-Reference - Message Reference of sent message. @hide */
+    @UnsupportedAppUsage
     public int mMessageRef;
 
     // TODO(): This class is duplicated in SmsMessage.java. Refactor accordingly.
     public static abstract class SubmitPduBase  {
+        @UnsupportedAppUsage
         public byte[] encodedScAddress; // Null if not applicable.
+        @UnsupportedAppUsage
         public byte[] encodedMessage;
 
         @Override
@@ -106,6 +118,7 @@
      * Returns the address of the SMS service center that relayed this message
      * or null if there is none.
      */
+    @UnsupportedAppUsage
     public String getServiceCenterAddress() {
         return mScAddress;
     }
@@ -114,6 +127,7 @@
      * Returns the originating address (sender) of this SMS message in String
      * form or null if unavailable
      */
+    @UnsupportedAppUsage
     public String getOriginatingAddress() {
         if (mOriginatingAddress == null) {
             return null;
@@ -127,6 +141,7 @@
      * was from an email gateway. Returns null if originating address
      * unavailable.
      */
+    @UnsupportedAppUsage
     public String getDisplayOriginatingAddress() {
         if (mIsEmail) {
             return mEmailFrom;
@@ -139,6 +154,7 @@
      * Returns the message body as a String, if it exists and is text based.
      * @return message body is there is one, otherwise null
      */
+    @UnsupportedAppUsage
     public String getMessageBody() {
         return mMessageBody;
     }
@@ -152,6 +168,7 @@
      * Returns the message body, or email message body if this message was from
      * an email gateway. Returns null if message body unavailable.
      */
+    @UnsupportedAppUsage
     public String getDisplayMessageBody() {
         if (mIsEmail) {
             return mEmailBody;
@@ -164,6 +181,7 @@
      * Unofficial convention of a subject line enclosed in parens empty string
      * if not present
      */
+    @UnsupportedAppUsage
     public String getPseudoSubject() {
         return mPseudoSubject == null ? "" : mPseudoSubject;
     }
@@ -171,6 +189,7 @@
     /**
      * Returns the service centre timestamp in currentTimeMillis() format
      */
+    @UnsupportedAppUsage
     public long getTimestampMillis() {
         return mScTimeMillis;
     }
@@ -204,12 +223,14 @@
     /**
      * Get protocol identifier.
      */
+    @UnsupportedAppUsage
     public abstract int getProtocolIdentifier();
 
     /**
      * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
      * SMS
      */
+    @UnsupportedAppUsage
     public abstract boolean isReplace();
 
     /**
@@ -242,6 +263,7 @@
      * returns the user data section minus the user data header if one was
      * present.
      */
+    @UnsupportedAppUsage
     public byte[] getUserData() {
         return mUserData;
     }
@@ -251,6 +273,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     public SmsHeader getUserDataHeader() {
         return mUserDataHeader;
     }
@@ -279,17 +302,20 @@
      *         See TS 23.040, 9.9.2.3.15 for a description of other possible
      *         values.
      */
+    @UnsupportedAppUsage
     public abstract int getStatus();
 
     /**
      * Return true iff the message is a SMS-STATUS-REPORT message.
      */
+    @UnsupportedAppUsage
     public abstract boolean isStatusReportMessage();
 
     /**
      * Returns true iff the <code>TP-Reply-Path</code> bit is set in
      * this message.
      */
+    @UnsupportedAppUsage
     public abstract boolean isReplyPathPresent();
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/SmsRawData.java b/telephony/java/com/android/internal/telephony/SmsRawData.java
index 891d942..18727f3 100644
--- a/telephony/java/com/android/internal/telephony/SmsRawData.java
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.java
@@ -17,6 +17,7 @@
 
 package com.android.internal.telephony;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,6 +28,7 @@
     byte[] data;
 
     //Static Methods
+    @UnsupportedAppUsage
     public static final Parcelable.Creator<SmsRawData> CREATOR
             = new Parcelable.Creator<SmsRawData> (){
         public SmsRawData createFromParcel(Parcel source) {
@@ -43,10 +45,12 @@
     };
 
     // Constructor
+    @UnsupportedAppUsage
     public SmsRawData(byte[] data) {
         this.data = data;
     }
 
+    @UnsupportedAppUsage
     public byte[] getBytes() {
         return data;
     }
diff --git a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
index edadd6e..590bd67 100644
--- a/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpLeaseRepositoryTest.java
@@ -34,8 +34,8 @@
 import android.annotation.NonNull;
 import android.net.IpPrefix;
 import android.net.MacAddress;
-import android.net.dhcp.DhcpLeaseRepository.Clock;
 import android.net.util.SharedLog;
+import android.net.dhcp.DhcpServer.Clock;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
diff --git a/tests/net/java/android/net/dhcp/DhcpServerTest.java b/tests/net/java/android/net/dhcp/DhcpServerTest.java
new file mode 100644
index 0000000..66db5a8
--- /dev/null
+++ b/tests/net/java/android/net/dhcp/DhcpServerTest.java
@@ -0,0 +1,314 @@
+/*
+ * 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.dhcp;
+
+import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
+import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
+import static android.net.dhcp.DhcpPacket.INADDR_ANY;
+import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doNothing;
+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 static java.net.InetAddress.parseNumericAddress;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkAddress;
+import android.net.MacAddress;
+import android.net.dhcp.DhcpLeaseRepository.InvalidAddressException;
+import android.net.dhcp.DhcpLeaseRepository.OutOfAddressesException;
+import android.net.dhcp.DhcpServer.Clock;
+import android.net.dhcp.DhcpServer.Dependencies;
+import android.net.util.InterfaceParams;
+import android.net.util.SharedLog;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.net.Inet4Address;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DhcpServerTest {
+    private static final String PROP_DEXMAKER_SHARE_CLASSLOADER = "dexmaker.share_classloader";
+    private static final String TEST_IFACE = "testiface";
+    private static final MacAddress TEST_IFACE_MAC = MacAddress.fromString("11:22:33:44:55:66");
+    private static final InterfaceParams TEST_IFACEPARAMS =
+            new InterfaceParams(TEST_IFACE, 1, TEST_IFACE_MAC);
+
+    private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2");
+    private static final LinkAddress TEST_SERVER_LINKADDR = new LinkAddress(TEST_SERVER_ADDR, 20);
+    private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124")));
+    private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127")));
+    private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>(
+            Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201")));
+    private static final long TEST_LEASE_TIME_SECS = 3600L;
+    private static final int TEST_MTU = 1500;
+
+    private static final int TEST_TRANSACTION_ID = 123;
+    private static final byte[] TEST_CLIENT_MAC_BYTES = new byte [] { 1, 2, 3, 4, 5, 6 };
+    private static final MacAddress TEST_CLIENT_MAC = MacAddress.fromBytes(TEST_CLIENT_MAC_BYTES);
+    private static final Inet4Address TEST_CLIENT_ADDR = parseAddr("192.168.0.42");
+
+    private static final long TEST_CLOCK_TIME = 1234L;
+    private static final int TEST_LEASE_EXPTIME_SECS = 3600;
+    private static final DhcpLease TEST_LEASE = new DhcpLease(null, TEST_CLIENT_MAC,
+            TEST_CLIENT_ADDR, TEST_LEASE_EXPTIME_SECS*1000L + TEST_CLOCK_TIME, null /* hostname */);
+
+    @NonNull @Mock
+    private Dependencies mDeps;
+    @NonNull @Mock
+    private DhcpLeaseRepository mRepository;
+    @NonNull @Mock
+    private Clock mClock;
+    @NonNull @Mock
+    private DhcpPacketListener mPacketListener;
+
+    @NonNull @Captor
+    private ArgumentCaptor<ByteBuffer> mSentPacketCaptor;
+    @NonNull @Captor
+    private ArgumentCaptor<Inet4Address> mResponseDstAddrCaptor;
+
+    @NonNull
+    private TestLooper mLooper;
+    @NonNull
+    private DhcpServer mServer;
+
+    @Nullable
+    private String mPrevShareClassloaderProp;
+
+    @Before
+    public void setUp() throws Exception {
+        // Allow mocking package-private classes
+        mPrevShareClassloaderProp = System.getProperty(PROP_DEXMAKER_SHARE_CLASSLOADER);
+        System.setProperty(PROP_DEXMAKER_SHARE_CLASSLOADER, "true");
+        MockitoAnnotations.initMocks(this);
+
+        when(mDeps.makeLeaseRepository(any(), any(), any())).thenReturn(mRepository);
+        when(mDeps.makeClock()).thenReturn(mClock);
+        when(mDeps.makePacketListener()).thenReturn(mPacketListener);
+        doNothing().when(mDeps)
+                .sendPacket(any(), mSentPacketCaptor.capture(), mResponseDstAddrCaptor.capture());
+        when(mClock.elapsedRealtime()).thenReturn(TEST_CLOCK_TIME);
+
+        final DhcpServingParams servingParams = new DhcpServingParams.Builder()
+                .setDefaultRouters(TEST_DEFAULT_ROUTERS)
+                .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS)
+                .setDnsServers(TEST_DNS_SERVERS)
+                .setServerAddr(TEST_SERVER_LINKADDR)
+                .setLinkMtu(TEST_MTU)
+                .setExcludedAddrs(TEST_EXCLUDED_ADDRS)
+                .build();
+
+        mLooper = new TestLooper();
+        mServer = new DhcpServer(mLooper.getLooper(), TEST_IFACEPARAMS, servingParams,
+                new SharedLog(DhcpServerTest.class.getSimpleName()), mDeps);
+
+        mServer.start();
+        mLooper.dispatchAll();
+    }
+
+    @After
+    public void tearDown() {
+        // Calling stop() several times is not an issue
+        mServer.stop();
+        System.setProperty(PROP_DEXMAKER_SHARE_CLASSLOADER,
+                (mPrevShareClassloaderProp == null ? "" : mPrevShareClassloaderProp));
+    }
+
+    @Test
+    public void testStart() throws Exception {
+        verify(mPacketListener, times(1)).start();
+    }
+
+    @Test
+    public void testStop() throws Exception {
+        mServer.stop();
+        mLooper.dispatchAll();
+        verify(mPacketListener, times(1)).stop();
+    }
+
+    @Test
+    public void testDiscover() throws Exception {
+        // TODO: refactor packet construction to eliminate unnecessary/confusing/duplicate fields
+        when(mRepository.getOffer(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
+                eq(INADDR_ANY) /* relayAddr */, isNull() /* reqAddr */, isNull() /* hostname */))
+                .thenReturn(TEST_LEASE);
+
+        final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
+                (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
+                false /* broadcast */, INADDR_ANY /* srcIp */);
+        mServer.processPacket(discover, DHCP_CLIENT);
+
+        assertResponseSentTo(TEST_CLIENT_ADDR);
+        final DhcpOfferPacket packet = assertOffer(getPacket());
+        assertMatchesTestLease(packet);
+    }
+
+    @Test
+    public void testDiscover_OutOfAddresses() throws Exception {
+        when(mRepository.getOffer(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
+                eq(INADDR_ANY) /* relayAddr */, isNull() /* reqAddr */, isNull() /* hostname */))
+                .thenThrow(new OutOfAddressesException("Test exception"));
+
+        final DhcpDiscoverPacket discover = new DhcpDiscoverPacket(TEST_TRANSACTION_ID,
+                (short) 0 /* secs */, INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES,
+                false /* broadcast */, INADDR_ANY /* srcIp */);
+        mServer.processPacket(discover, DHCP_CLIENT);
+
+        assertResponseSentTo(INADDR_BROADCAST);
+        final DhcpNakPacket packet = assertNak(getPacket());
+        assertMatchesClient(packet);
+    }
+
+    private DhcpRequestPacket makeRequestSelectingPacket() {
+        final DhcpRequestPacket request = new DhcpRequestPacket(TEST_TRANSACTION_ID,
+                (short) 0 /* secs */, INADDR_ANY /* clientIp */, INADDR_ANY /* relayIp */,
+                TEST_CLIENT_MAC_BYTES, false /* broadcast */);
+        request.mServerIdentifier = TEST_SERVER_ADDR;
+        request.mRequestedIp = TEST_CLIENT_ADDR;
+        return request;
+    }
+
+    @Test
+    public void testRequest_Selecting_Ack() throws Exception {
+        when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
+                eq(INADDR_ANY) /* clientAddr */, eq(TEST_CLIENT_ADDR) /* reqAddr */,
+                eq(true) /* sidSet */, isNull() /* hostname */))
+                .thenReturn(TEST_LEASE);
+
+        final DhcpRequestPacket request = makeRequestSelectingPacket();
+        mServer.processPacket(request, DHCP_CLIENT);
+
+        assertResponseSentTo(TEST_CLIENT_ADDR);
+        final DhcpAckPacket packet = assertAck(getPacket());
+        assertMatchesTestLease(packet);
+    }
+
+    @Test
+    public void testRequest_Selecting_Nak() throws Exception {
+        when(mRepository.requestLease(isNull(), eq(TEST_CLIENT_MAC),
+                eq(INADDR_ANY) /* clientAddr */, eq(TEST_CLIENT_ADDR) /* reqAddr */,
+                eq(true) /* sidSet */, isNull() /* hostname */))
+                .thenThrow(new InvalidAddressException("Test error"));
+
+        final DhcpRequestPacket request = makeRequestSelectingPacket();
+        mServer.processPacket(request, DHCP_CLIENT);
+
+        assertResponseSentTo(INADDR_BROADCAST);
+        final DhcpNakPacket packet = assertNak(getPacket());
+        assertMatchesClient(packet);
+    }
+
+    @Test
+    public void testRequest_Selecting_WrongClientPort() throws Exception {
+        final DhcpRequestPacket request = makeRequestSelectingPacket();
+        mServer.processPacket(request, 50000);
+
+        verify(mRepository, never()).requestLease(any(), any(), any(), any(), anyBoolean(), any());
+        verify(mDeps, never()).sendPacket(any(), any(), any());
+    }
+
+    @Test
+    public void testRelease() throws Exception {
+        final DhcpReleasePacket release = new DhcpReleasePacket(TEST_TRANSACTION_ID,
+                TEST_SERVER_ADDR, TEST_CLIENT_ADDR,
+                INADDR_ANY /* relayIp */, TEST_CLIENT_MAC_BYTES);
+        mServer.processPacket(release, DHCP_CLIENT);
+
+        verify(mRepository, times(1))
+                .releaseLease(isNull(), eq(TEST_CLIENT_MAC), eq(TEST_CLIENT_ADDR));
+    }
+
+    /* TODO: add more tests once packet construction is refactored, including:
+     *  - usage of giaddr
+     *  - usage of broadcast bit
+     *  - other request states (init-reboot/renewing/rebinding)
+     */
+
+    private void assertMatchesTestLease(@NonNull DhcpPacket packet) {
+        assertMatchesClient(packet);
+        assertFalse(packet.hasExplicitClientId());
+        assertEquals(TEST_SERVER_ADDR, packet.mServerIdentifier);
+        assertEquals(TEST_CLIENT_ADDR, packet.mYourIp);
+        assertNotNull(packet.mLeaseTime);
+        assertEquals(TEST_LEASE_EXPTIME_SECS, (int) packet.mLeaseTime);
+        assertNull(packet.mHostName);
+    }
+
+    private void assertMatchesClient(@NonNull DhcpPacket packet) {
+        assertEquals(TEST_TRANSACTION_ID, packet.mTransId);
+        assertEquals(TEST_CLIENT_MAC, MacAddress.fromBytes(packet.mClientMac));
+    }
+
+    private void assertResponseSentTo(@NonNull Inet4Address addr) {
+        assertEquals(addr, mResponseDstAddrCaptor.getValue());
+    }
+
+    private static DhcpNakPacket assertNak(@Nullable DhcpPacket packet) {
+        assertTrue(packet instanceof DhcpNakPacket);
+        return (DhcpNakPacket) packet;
+    }
+
+    private static DhcpAckPacket assertAck(@Nullable DhcpPacket packet) {
+        assertTrue(packet instanceof DhcpAckPacket);
+        return (DhcpAckPacket) packet;
+    }
+
+    private static DhcpOfferPacket assertOffer(@Nullable DhcpPacket packet) {
+        assertTrue(packet instanceof DhcpOfferPacket);
+        return (DhcpOfferPacket) packet;
+    }
+
+    private DhcpPacket getPacket() throws Exception {
+        verify(mDeps, times(1)).sendPacket(any(), any(), any());
+        return DhcpPacket.decodeFullPacket(mSentPacketCaptor.getValue(), ENCAP_BOOTP);
+    }
+
+    private static Inet4Address parseAddr(@Nullable String inet4Addr) {
+        return (Inet4Address) parseNumericAddress(inet4Addr);
+    }
+}
diff --git a/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
index b017130..b399b0d 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkMonitorTest.java
@@ -106,6 +106,7 @@
                 anyString())).thenReturn(TEST_HTTP_URL);
         when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_HTTPS_URL),
                 anyString())).thenReturn(TEST_HTTPS_URL);
+        when(mNetwork.getPrivateDnsBypassingCopy()).thenReturn(mNetwork);
 
         when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephony);
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifi);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 1e03891..e37a856 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -17,14 +17,14 @@
 package android.net.wifi;
 
 import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
-import android.os.Parcel;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.EnumMap;
 import java.util.Locale;
@@ -540,9 +540,13 @@
         dest.writeInt(mMeteredHint ? 1 : 0);
         dest.writeInt(mEphemeral ? 1 : 0);
         dest.writeInt(score);
+        dest.writeLong(txSuccess);
         dest.writeDouble(txSuccessRate);
+        dest.writeLong(txRetries);
         dest.writeDouble(txRetriesRate);
+        dest.writeLong(txBad);
         dest.writeDouble(txBadRate);
+        dest.writeLong(rxSuccess);
         dest.writeDouble(rxSuccessRate);
         mSupplicantState.writeToParcel(dest, flags);
     }
@@ -570,9 +574,13 @@
                 info.mMeteredHint = in.readInt() != 0;
                 info.mEphemeral = in.readInt() != 0;
                 info.score = in.readInt();
+                info.txSuccess = in.readLong();
                 info.txSuccessRate = in.readDouble();
+                info.txRetries = in.readLong();
                 info.txRetriesRate = in.readDouble();
+                info.txBad = in.readLong();
                 info.txBadRate = in.readDouble();
+                info.rxSuccess = in.readLong();
                 info.rxSuccessRate = in.readDouble();
                 info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
                 return info;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b56a758..7a91347 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -981,6 +981,7 @@
     private AsyncChannel mAsyncChannel;
     private CountDownLatch mConnected;
     private Looper mLooper;
+    private boolean mVerboseLoggingEnabled = false;
 
     /* LocalOnlyHotspot callback message types */
     /** @hide */
@@ -1013,6 +1014,7 @@
         mService = service;
         mLooper = looper;
         mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+        updateVerboseLoggingEnabledFromService();
     }
 
     /**
@@ -2475,7 +2477,7 @@
      *
      * @hide
      */
-    private static class SoftApCallbackProxy extends ISoftApCallback.Stub {
+    private class SoftApCallbackProxy extends ISoftApCallback.Stub {
         private final Handler mHandler;
         private final SoftApCallback mCallback;
 
@@ -2486,8 +2488,10 @@
 
         @Override
         public void onStateChanged(int state, int failureReason) {
-            Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" +
-                    failureReason);
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state
+                        + ", failureReason=" + failureReason);
+            }
             mHandler.post(() -> {
                 mCallback.onStateChanged(state, failureReason);
             });
@@ -2495,7 +2499,9 @@
 
         @Override
         public void onNumClientsChanged(int numClients) {
-            Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
+            }
             mHandler.post(() -> {
                 mCallback.onNumClientsChanged(numClients);
             });
@@ -3786,7 +3792,7 @@
      *
      * @hide
      */
-    private static class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub {
+    private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub {
         private final Handler mHandler;
         private final TrafficStateCallback mCallback;
 
@@ -3797,7 +3803,9 @@
 
         @Override
         public void onStateChanged(int state) {
-            Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state);
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state);
+            }
             mHandler.post(() -> {
                 mCallback.onStateChanged(state);
             });
@@ -3854,4 +3862,12 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Helper method to update the local verbose logging flag based on the verbose logging
+     * level from wifi service.
+     */
+    private void updateVerboseLoggingEnabledFromService() {
+        mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0;
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
new file mode 100644
index 0000000..f5a8b29
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiInfo}.
+ */
+@SmallTest
+public class WifiInfoTest {
+    private static final long TEST_TX_SUCCESS = 1;
+    private static final long TEST_TX_RETRIES = 2;
+    private static final long TEST_TX_BAD = 3;
+    private static final long TEST_RX_SUCCESS = 4;
+
+    /**
+     *  Verify parcel write/read with WifiInfo.
+     */
+    @Test
+    public void testWifiInfoParcelWriteRead() throws Exception {
+        WifiInfo writeWifiInfo = new WifiInfo();
+        writeWifiInfo.txSuccess = TEST_TX_SUCCESS;
+        writeWifiInfo.txRetries = TEST_TX_RETRIES;
+        writeWifiInfo.txBad = TEST_TX_BAD;
+        writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
+
+        Parcel parcel = Parcel.obtain();
+        writeWifiInfo.writeToParcel(parcel, 0);
+        // Rewind the pointer to the head of the parcel.
+        parcel.setDataPosition(0);
+        WifiInfo readWifiInfo = WifiInfo.CREATOR.createFromParcel(parcel);
+
+        assertNotNull(readWifiInfo);
+        assertEquals(TEST_TX_SUCCESS, readWifiInfo.txSuccess);
+        assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
+        assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
+        assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 5058080..e40b657a 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -93,6 +93,7 @@
 
         mWifiServiceMessenger = new Messenger(mHandler);
         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
+        verify(mWifiService).getVerboseLoggingLevel();
     }
 
     /**