Merge "Don't apply rounded-corner animation on non-default display" into qt-dev
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
index d6e8ab2..8847456 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.AssetManager;
+import android.content.res.Resources;
 import android.graphics.Typeface;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
@@ -26,6 +27,8 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.perftests.core.R;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -104,4 +107,15 @@
 
         outFile.delete();
     }
+
+    @Test
+    public void testCreate_fromResources() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final Resources r = InstrumentationRegistry.getContext().getResources();
+
+        while (state.keepRunning()) {
+            Typeface face = r.getFont(R.font.samplefont);
+        }
+    }
+
 }
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
index 4d22d0b..3a2e528 100644
--- a/api/TEST_MAPPING
+++ b/api/TEST_MAPPING
@@ -5,9 +5,11 @@
     },
     {
       "name": "CtsSystemApiSignatureTestCases"
-    },
+    }
+  ],
+  "imports": [
     {
-      "name": "GtsUnofficialApisUsageTestCases"
+      "path": "vendor/xts/gts-tests/hostsidetests/api"
     }
   ]
 }
diff --git a/api/current.txt b/api/current.txt
index d2f63fa..0f4231d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27245,7 +27245,7 @@
     method @Nullable public CharSequence getQueueTitle();
     method public int getRatingType();
     method @Nullable public android.app.PendingIntent getSessionActivity();
-    method @Nullable public android.os.Bundle getSessionInfo();
+    method @NonNull public android.os.Bundle getSessionInfo();
     method @NonNull public android.media.session.MediaSession.Token getSessionToken();
     method @NonNull public android.media.session.MediaController.TransportControls getTransportControls();
     method public void registerCallback(@NonNull android.media.session.MediaController.Callback);
diff --git a/api/system-current.txt b/api/system-current.txt
index 99779de..3028ae8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1714,7 +1714,6 @@
     field public static final int MATCH_ANY_USER = 4194304; // 0x400000
     field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000
     field public static final int MATCH_INSTANT = 8388608; // 0x800000
-    field public static boolean RESTRICTED_PERMISSIONS_ENABLED;
     field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
     field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
     field public static final int RESTRICTION_NONE = 0; // 0x0
@@ -3079,16 +3078,15 @@
   }
 
   public final class GnssCapabilities {
-    method public boolean hasCapability(int);
-    field public static final int GEOFENCING = 2; // 0x2
-    field public static final int LOW_POWER_MODE = 0; // 0x0
-    field public static final int MEASUREMENTS = 3; // 0x3
-    field public static final int MEASUREMENT_CORRECTIONS = 5; // 0x5
-    field public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH = 7; // 0x7
-    field public static final int MEASUREMENT_CORRECTIONS_LOS_SATS = 6; // 0x6
-    field public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 8; // 0x8
-    field public static final int NAV_MESSAGES = 4; // 0x4
-    field public static final int SATELLITE_BLACKLIST = 1; // 0x1
+    method public boolean hasGeofencing();
+    method public boolean hasLowPowerMode();
+    method public boolean hasMeasurementCorrections();
+    method public boolean hasMeasurementCorrectionsExcessPathLength();
+    method public boolean hasMeasurementCorrectionsLosSats();
+    method public boolean hasMeasurementCorrectionsReflectingPane();
+    method public boolean hasMeasurements();
+    method public boolean hasNavMessages();
+    method public boolean hasSatelliteBlacklist();
   }
 
   public final class GnssMeasurementCorrections implements android.os.Parcelable {
@@ -3399,7 +3397,7 @@
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
     method @Nullable public String getExtraLocationControllerPackage();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
-    method @Nullable public android.location.GnssCapabilities getGnssCapabilities();
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GnssCapabilities getGnssCapabilities();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isExtraLocationControllerPackageEnabled();
     method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
@@ -6014,17 +6012,6 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void resetToDefaults(@NonNull android.content.ContentResolver, @Nullable String);
     field public static final String APP_STANDBY_ENABLED = "app_standby_enabled";
     field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
-    field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
-    field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
-    field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
-    field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
-    field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
-    field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
-    field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
-    field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
-    field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
     field public static final String CARRIER_APP_NAMES = "carrier_app_names";
     field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
     field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
diff --git a/api/test-current.txt b/api/test-current.txt
index 63c8df0..3cde3f2 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2265,17 +2265,6 @@
     field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
     field public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode";
     field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
-    field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
-    field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
-    field public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
-    field public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
-    field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
-    field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
-    field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
-    field public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS = "captive_portal_other_fallback_urls";
-    field public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
-    field public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
     field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
     field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index fa9a77a..83c034b 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -39,6 +39,8 @@
 using android::idmap2::CommandLineOptions;
 using android::idmap2::Error;
 using android::idmap2::Idmap;
+using android::idmap2::kPolicyOdm;
+using android::idmap2::kPolicyOem;
 using android::idmap2::kPolicyProduct;
 using android::idmap2::kPolicyPublic;
 using android::idmap2::kPolicySystem;
@@ -93,6 +95,8 @@
 
 std::vector<std::string> PoliciesForPath(const std::string& apk_path) {
   static const std::vector<std::pair<std::string, std::string>> values = {
+      {"/odm/", kPolicyOdm},
+      {"/oem/", kPolicyOem},
       {"/product/", kPolicyProduct},
       {"/system/", kPolicySystem},
       {"/vendor/", kPolicyVendor},
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
index 8f9a5f8..9c9b6c7 100644
--- a/cmds/incidentd/Android.bp
+++ b/cmds/incidentd/Android.bp
@@ -59,6 +59,12 @@
         "libservices",
         "libutils",
         "libprotobuf-cpp-lite",
+        "libcrypto",
+        "libkeystore_aidl",
+        "libkeystore_binder",
+        "libkeystore_parcelables",
+        "android.hardware.keymaster@4.0",
+        "libkeymaster4support",
     ],
 
     static_libs: [
@@ -111,6 +117,8 @@
         "src/incidentd_util.cpp",
         "src/proto_util.cpp",
         "src/report_directory.cpp",
+        "src/cipher/IncidentKeyStore.cpp",
+        "src/cipher/ProtoEncryption.cpp",
         "src/**/*.proto",
     ],
 
@@ -132,6 +140,12 @@
         "libprotoutil",
         "libservices",
         "libutils",
+        "libcrypto",
+        "libkeystore_aidl",
+        "libkeystore_binder",
+        "libkeystore_parcelables",
+        "android.hardware.keymaster@4.0",
+        "libkeymaster4support",
     ],
 
     target: {
diff --git a/cmds/incidentd/src/Privacy.cpp b/cmds/incidentd/src/Privacy.cpp
index 386303b..91f0dd3 100644
--- a/cmds/incidentd/src/Privacy.cpp
+++ b/cmds/incidentd/src/Privacy.cpp
@@ -37,6 +37,8 @@
     return NULL;
 }
 
+bool sectionEncryption(int section_id) { return section_id == 3025 /*restricted image section*/; }
+
 static bool isAllowed(const uint8_t policy, const uint8_t check) {
     switch (check) {
         case PRIVACY_POLICY_LOCAL:
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index fc8caae..b599c1c4 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -87,6 +87,9 @@
     uint8_t mPolicy;
 };
 
+// TODO: Add privacy flag in incident.proto and auto generate it inside Privacy.
+bool sectionEncryption(int section_id);
+
 }  // namespace incidentd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/incidentd/src/PrivacyFilter.cpp b/cmds/incidentd/src/PrivacyFilter.cpp
index 7126322..e8fa4f4 100644
--- a/cmds/incidentd/src/PrivacyFilter.cpp
+++ b/cmds/incidentd/src/PrivacyFilter.cpp
@@ -16,15 +16,18 @@
 #define DEBUG false
 #include "Log.h"
 
-#include "incidentd_util.h"
 #include "PrivacyFilter.h"
-#include "proto_util.h"
 
 #include <android-base/file.h>
-#include <android/util/protobuf.h>
 #include <android/util/ProtoFileReader.h>
+#include <android/util/protobuf.h>
 #include <log/log.h>
 
+#include "cipher/IncidentKeyStore.h"
+#include "cipher/ProtoEncryption.h"
+#include "incidentd_util.h"
+#include "proto_util.h"
+
 namespace android {
 namespace os {
 namespace incidentd {
@@ -141,6 +144,8 @@
      */
     status_t writeData(int fd);
 
+    sp<ProtoReader> getData() { return mData; }
+
 private:
     /**
      * The global set of field --> required privacy level mapping.
@@ -247,8 +252,47 @@
     mOutputs.push_back(output);
 }
 
-status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel,
-        size_t* maxSize) {
+static void write_section_to_file(int sectionId, FieldStripper& fieldStripper, sp<FilterFd> output,
+                                  bool encryptIfNeeded) {
+    status_t err;
+
+    if (sectionEncryption(sectionId) && encryptIfNeeded) {
+        ProtoEncryptor encryptor(fieldStripper.getData());
+        size_t encryptedSize = encryptor.encrypt();
+
+        if (encryptedSize <= 0) {
+            output->onWriteError(BAD_VALUE);
+            return;
+        }
+        err = write_section_header(output->getFd(), sectionId, encryptedSize);
+        VLOG("Encrypted: write section header size %lu", (unsigned long)encryptedSize);
+
+        encryptor.flush(output->getFd());
+
+        if (err != NO_ERROR) {
+            output->onWriteError(err);
+            return;
+        }
+    } else {
+        err = write_section_header(output->getFd(), sectionId, fieldStripper.dataSize());
+        VLOG("No encryption: write section header size %lu",
+             (unsigned long)fieldStripper.dataSize());
+
+        if (err != NO_ERROR) {
+            output->onWriteError(err);
+            return;
+        }
+
+        err = fieldStripper.writeData(output->getFd());
+        if (err != NO_ERROR) {
+            output->onWriteError(err);
+            return;
+        }
+    }
+}
+
+status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize,
+                                  bool encryptIfNeeded) {
     status_t err;
 
     if (maxSize != NULL) {
@@ -258,9 +302,9 @@
     // Order the writes by privacy filter, with increasing levels of filtration,k
     // so we can do the filter once, and then write many times.
     sort(mOutputs.begin(), mOutputs.end(),
-        [](const sp<FilterFd>& a, const sp<FilterFd>& b) -> bool { 
-            return a->getPrivacyPolicy() < b->getPrivacyPolicy();
-        });
+         [](const sp<FilterFd>& a, const sp<FilterFd>& b) -> bool {
+             return a->getPrivacyPolicy() < b->getPrivacyPolicy();
+         });
 
     uint8_t privacyPolicy = PRIVACY_POLICY_LOCAL; // a.k.a. no filtering
     FieldStripper fieldStripper(mRestrictions, buffer.data()->read(), bufferLevel);
@@ -279,17 +323,7 @@
         // Write the resultant buffer to the fd, along with the header.
         ssize_t dataSize = fieldStripper.dataSize();
         if (dataSize > 0) {
-            err = write_section_header(output->getFd(), mSectionId, dataSize);
-            if (err != NO_ERROR) {
-                output->onWriteError(err);
-                continue;
-            }
-
-            err = fieldStripper.writeData(output->getFd());
-            if (err != NO_ERROR) {
-                output->onWriteError(err);
-                continue;
-            }
+            write_section_to_file(mSectionId, fieldStripper, output, encryptIfNeeded);
         }
 
         if (maxSize != NULL) {
@@ -334,14 +368,25 @@
         uint32_t fieldId = read_field_id(fieldTag);
         uint8_t wireType = read_wire_type(fieldTag);
         if (wireType == WIRE_TYPE_LENGTH_DELIMITED && args.containsSection(fieldId)) {
+            VLOG("Read section %d", fieldId);
             // We need this field, but we need to strip it to the level provided in args.
             PrivacyFilter filter(fieldId, get_privacy_of_section(fieldId));
             filter.addFd(new ReadbackFilterFd(args.getPrivacyPolicy(), to));
 
             // Read this section from the reader into an FdBuffer
             size_t sectionSize = reader->readRawVarint();
+
             FdBuffer sectionData;
-            err = sectionData.write(reader, sectionSize);
+
+            // Write data to FdBuffer, if the section was encrypted, decrypt first.
+            if (sectionEncryption(fieldId)) {
+                VLOG("sectionSize %lu", (unsigned long)sectionSize);
+                ProtoDecryptor decryptor(reader, sectionSize);
+                err = decryptor.decryptAndFlush(&sectionData);
+            } else {
+                err = sectionData.write(reader, sectionSize);
+            }
+
             if (err != NO_ERROR) {
                 ALOGW("filter_and_write_report FdBuffer.write failed (this shouldn't happen): %s",
                         strerror(-err));
@@ -349,7 +394,8 @@
             }
 
             // Do the filter and write.
-            err = filter.writeData(sectionData, bufferLevel, nullptr);
+            err = filter.writeData(sectionData, bufferLevel, nullptr,
+                                   false /* do not encrypt again*/);
             if (err != NO_ERROR) {
                 ALOGW("filter_and_write_report filter.writeData had an error: %s", strerror(-err));
                 return err;
@@ -358,6 +404,7 @@
             // We don't need this field.  Incident does not have any direct children
             // other than sections.  So just skip them.
             write_field_or_skip(NULL, reader, fieldTag, true);
+            VLOG("Skip this.... section %d", fieldId);
         }
     }
 
diff --git a/cmds/incidentd/src/PrivacyFilter.h b/cmds/incidentd/src/PrivacyFilter.h
index 76b2849..d426db9 100644
--- a/cmds/incidentd/src/PrivacyFilter.h
+++ b/cmds/incidentd/src/PrivacyFilter.h
@@ -82,8 +82,14 @@
      * was written (i.e. after filtering).
      *
      * The buffer is assumed to have already been filtered to bufferLevel.
+     *
+     * This function can be called when persisting data to disk or when sending
+     * data to client. In the former case, we need to encrypt the data when that
+     * section requires encryption. In the latter case, we shouldn't send the
+     * unencrypted data to client.
      */
-    status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize);
+    status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize,
+                       bool encryptIfNeeded);
 
 private:
     int mSectionId;
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 218c1b2..322b972 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -447,7 +447,8 @@
         }
     });
 
-    return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize);
+    return filter.writeData(buffer, PRIVACY_POLICY_LOCAL, &mMaxSectionDataFilteredSize,
+                            true /*encrypt if needed*/);
 }
 
 
diff --git a/cmds/incidentd/src/cipher/IncidentKeyStore.cpp b/cmds/incidentd/src/cipher/IncidentKeyStore.cpp
new file mode 100644
index 0000000..ae0a920
--- /dev/null
+++ b/cmds/incidentd/src/cipher/IncidentKeyStore.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Log.h"
+
+#include "IncidentKeyStore.h"
+
+#include <sys/stat.h>
+
+static constexpr size_t AES_KEY_BYTES = 32;
+static constexpr size_t GCM_MAC_BYTES = 16;
+constexpr char kKeyname[] = "IncidentKey";
+
+namespace android {
+namespace os {
+namespace incidentd {
+
+using namespace keystore;
+using std::string;
+
+IncidentKeyStore& IncidentKeyStore::getInstance() {
+    static IncidentKeyStore sInstance(new keystore::KeystoreClientImpl);
+    return sInstance;
+}
+
+bool IncidentKeyStore::encrypt(const string& data, int32_t flags, string* output) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (data.empty()) {
+        ALOGW("IncidentKeyStore: Encrypt empty data?!");
+        return false;
+    }
+    if (!mClient->doesKeyExist(kKeyname)) {
+        auto gen_result = generateKeyLocked(kKeyname, 0);
+        if (!gen_result.isOk()) {
+            ALOGE("IncidentKeyStore: Key generate failed.");
+            return false;
+        }
+    }
+    if (!mClient->encryptWithAuthentication(kKeyname, data, flags, output)) {
+        ALOGE("IncidentKeyStore: Encryption failed.");
+        return false;
+    }
+    return true;
+}
+
+bool IncidentKeyStore::decrypt(const std::string& input, string* output) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (input.empty()) {
+        ALOGE("IncidentKeyStore: Decrypt empty input?");
+        return false;
+    }
+    if (!mClient->decryptWithAuthentication(kKeyname, input, output)) {
+        ALOGE("IncidentKeyStore: Decryption failed.");
+        return false;
+    }
+    return true;
+}
+
+KeyStoreNativeReturnCode IncidentKeyStore::generateKeyLocked(const std::string& name,
+                                                             int32_t flags) {
+    auto paramBuilder = AuthorizationSetBuilder()
+                                .AesEncryptionKey(AES_KEY_BYTES * 8)
+                                .GcmModeMinMacLen(GCM_MAC_BYTES * 8)
+                                .Authorization(TAG_NO_AUTH_REQUIRED);
+
+    AuthorizationSet hardware_enforced_characteristics;
+    AuthorizationSet software_enforced_characteristics;
+    return mClient->generateKey(name, paramBuilder, flags, &hardware_enforced_characteristics,
+                                &software_enforced_characteristics);
+}
+
+}  // namespace incidentd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/incidentd/src/cipher/IncidentKeyStore.h b/cmds/incidentd/src/cipher/IncidentKeyStore.h
new file mode 100644
index 0000000..27611cd
--- /dev/null
+++ b/cmds/incidentd/src/cipher/IncidentKeyStore.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <keystore/keystore_client_impl.h>
+
+namespace android {
+namespace os {
+namespace incidentd {
+
+class IncidentKeyStore {
+public:
+    static IncidentKeyStore& getInstance();
+
+    IncidentKeyStore(keystore::KeystoreClient* client) : mClient(client) {}
+
+    /**
+     * Encrypt the plainText and output the encrypted message.
+     *
+     * Returns true on success and false otherwise.
+     * If the key has not been created yet, it will generate the key in KeyMaster.
+     */
+    bool encrypt(const std::string& plainText, int32_t flags, std::string* output);
+
+    /**
+     * Decrypt and output the decrypted message.
+     *
+     * Returns true on success and false otherwise.
+     */
+    bool decrypt(const std::string& encryptedData, std::string* output);
+
+private:
+    std::unique_ptr<keystore::KeystoreClient> mClient;
+    std::mutex mMutex;
+    keystore::KeyStoreNativeReturnCode generateKeyLocked(const std::string& name, int32_t flags);
+};
+
+}  // namespace incidentd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/incidentd/src/cipher/ProtoEncryption.cpp b/cmds/incidentd/src/cipher/ProtoEncryption.cpp
new file mode 100644
index 0000000..493796d
--- /dev/null
+++ b/cmds/incidentd/src/cipher/ProtoEncryption.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG true  // STOPSHIP if true
+#include "Log.h"
+
+#include "ProtoEncryption.h"
+
+#include <android/util/protobuf.h>
+
+#include "IncidentKeyStore.h"
+
+namespace android {
+namespace os {
+namespace incidentd {
+
+using android::util::FIELD_COUNT_REPEATED;
+using android::util::FIELD_TYPE_STRING;
+using android::util::ProtoOutputStream;
+using android::util::ProtoReader;
+using std::string;
+
+static const int FIELD_ID_BLOCK = 1;
+
+size_t ProtoEncryptor::encrypt() {
+    string block;
+    int i = 0;
+    // Read at most sBlockSize at a time and encrypt.
+    while (mReader->readBuffer() != NULL) {
+        size_t readBytes =
+                mReader->currentToRead() > sBlockSize ? sBlockSize : mReader->currentToRead();
+        block.resize(readBytes);
+        std::memcpy(block.data(), mReader->readBuffer(), readBytes);
+
+        string encrypted;
+        if (IncidentKeyStore::getInstance().encrypt(block, 0, &encrypted)) {
+            mOutputStream.write(FIELD_TYPE_STRING | FIELD_ID_BLOCK | FIELD_COUNT_REPEATED,
+                                encrypted);
+            VLOG("Block %d Encryption: original %lld now %lld", i++, (long long)readBytes,
+                 (long long)encrypted.length());
+            mReader->move(readBytes);
+        } else {
+            return 0;
+        }
+    }
+    return mOutputStream.size();
+}
+
+status_t ProtoEncryptor::flush(int fd) {
+    if (!mOutputStream.flush(fd)) {
+        return BAD_VALUE;
+    }
+    return NO_ERROR;
+}
+
+status_t ProtoDecryptor::readOneBlock(string* output) {
+    if (!mReader->hasNext()) {
+        return NO_ERROR;
+    }
+    uint64_t fieldTag = mReader->readRawVarint();
+    uint32_t fieldId = read_field_id(fieldTag);
+    uint8_t wireType = read_wire_type(fieldTag);
+    if (wireType == WIRE_TYPE_LENGTH_DELIMITED) {
+        // Read this section from the reader into an FdBuffer
+        size_t sectionSize = mReader->readRawVarint();
+        output->resize(sectionSize);
+        size_t pos = 0;
+        while (pos < sectionSize && mReader->readBuffer() != NULL) {
+            size_t toRead = (sectionSize - pos) > mReader->currentToRead()
+                                    ? mReader->currentToRead()
+                                    : (sectionSize - pos);
+            std::memcpy(&((output->data())[pos]), mReader->readBuffer(), toRead);
+            pos += toRead;
+            mReader->move(toRead);
+        }
+        if (pos != sectionSize) {
+            return BAD_VALUE;
+            ALOGE("Failed to read one block");
+        }
+    } else {
+        return BAD_VALUE;
+    }
+    return NO_ERROR;
+}
+
+status_t ProtoDecryptor::decryptAndFlush(FdBuffer* out) {
+    size_t mStartBytes = mReader->bytesRead();
+    size_t bytesRead = 0;
+    int i = 0;
+    status_t err = NO_ERROR;
+    // Let's read until we read mTotalSize. If any error occurs before that, make sure to move the
+    // read pointer so the caller can continue to read the following sections.
+    while (bytesRead < mTotalSize) {
+        string block;
+        err = readOneBlock(&block);
+        bytesRead = mReader->bytesRead() - mStartBytes;
+
+        if (err != NO_ERROR) {
+            break;
+        }
+
+        if (block.length() == 0) {
+            VLOG("Done reading all blocks");
+            break;
+        }
+
+        string decryptedBlock;
+        if ((IncidentKeyStore::getInstance()).decrypt(block, &decryptedBlock)) {
+            VLOG("Block %d Original Size %lu Decrypted size %lu", i++,
+                 (unsigned long)block.length(), (unsigned long)decryptedBlock.length());
+            out->write(reinterpret_cast<uint8_t*>(decryptedBlock.data()), decryptedBlock.length());
+        } else {
+            err = BAD_VALUE;
+            break;
+        }
+    }
+
+    if (bytesRead < mTotalSize) {
+        mReader->move(mTotalSize - bytesRead);
+    }
+    return err;
+}
+
+}  // namespace incidentd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/incidentd/src/cipher/ProtoEncryption.h b/cmds/incidentd/src/cipher/ProtoEncryption.h
new file mode 100644
index 0000000..5b72ca8
--- /dev/null
+++ b/cmds/incidentd/src/cipher/ProtoEncryption.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <android/util/ProtoOutputStream.h>
+#include <android/util/ProtoReader.h>
+#include <frameworks/base/cmds/incidentd/src/cipher/cipher_blocks.pb.h>
+
+#include "FdBuffer.h"
+
+namespace android {
+namespace os {
+namespace incidentd {
+
+// PlainText IncidentReport format
+// [section1_header(id, size, type)][section1_data] ...
+
+// Let's say section1 needs encryption
+// After encryption, it becomes
+// [section1_header(id, encrypted_size, type)][[cipher_block][cipher_block][cipher_block]..]
+
+// When clients read the report, it's decrypted, and written in its original format
+
+/**
+ * Takes a ProtoReader, encrypts its whole content -- which is one section, and flush to
+ * a file descriptor.
+ * The underlying encryption is done using Keystore binder APIs. We encrypt the data
+ * in blocks, and write to the file in android.os.incidentd.CipherBlocks format.
+ */
+class ProtoEncryptor {
+public:
+    ProtoEncryptor(const sp<android::util::ProtoReader>& reader) : mReader(reader){};
+
+    // Encrypt the data from ProtoReader, and store in CipherBlocks format.
+    // return the size of CipherBlocks.
+    size_t encrypt();
+
+    status_t flush(int fd);
+
+private:
+    static const size_t sBlockSize = 8 * 1024;
+    const sp<android::util::ProtoReader> mReader;
+    android::util::ProtoOutputStream mOutputStream;
+};
+
+// Read data from ProtoReader, which is in CipherBlocks proto format. Parse and decrypt
+// block by block.
+class ProtoDecryptor {
+public:
+    ProtoDecryptor(const sp<android::util::ProtoReader>& reader, size_t size)
+        : mReader(reader), mTotalSize(size){};
+    status_t decryptAndFlush(FdBuffer* out);
+
+private:
+    const sp<android::util::ProtoReader> mReader;
+
+    // Total size in bytes we should read from ProtoReader.
+    const size_t mTotalSize;
+
+    // Read one cipher block from ProtoReader, instead of reading the whole content
+    // and parse to CipherBlocks which could be huge.
+    status_t readOneBlock(std::string* output);
+};
+
+}  // namespace incidentd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/incidentd/src/cipher/cipher_blocks.proto b/cmds/incidentd/src/cipher/cipher_blocks.proto
new file mode 100644
index 0000000..5c7ed24
--- /dev/null
+++ b/cmds/incidentd/src/cipher/cipher_blocks.proto
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.os.incidentd;
+
+// This proto is never instantiated anywhere. It only exists to keep a record of the format of the
+// encrypted data on disk.
+message CipherBlocks {
+    repeated string blocks = 1;
+}
diff --git a/cmds/incidentd/tests/IncidentKeyStore_test.cpp b/cmds/incidentd/tests/IncidentKeyStore_test.cpp
new file mode 100644
index 0000000..2250fda
--- /dev/null
+++ b/cmds/incidentd/tests/IncidentKeyStore_test.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cipher/IncidentKeyStore.h"
+
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+using namespace android::os::incidentd;
+
+class IncidentKeyStoreTest : public ::testing::Test {
+protected:
+    std::unique_ptr<IncidentKeyStore> incidentKeyStore;
+    void SetUp() override {
+        android::ProcessState::self()->startThreadPool();
+        incidentKeyStore = std::make_unique<IncidentKeyStore>(
+                static_cast<keystore::KeystoreClient*>(new keystore::KeystoreClientImpl));
+    };
+    void TearDown() override { incidentKeyStore = nullptr; };
+};
+
+TEST_F(IncidentKeyStoreTest, test_encrypt_decrypt) {
+    std::string plaintext;
+    plaintext.resize(4 * 1024, 'a');
+
+    std::string encrypted;
+    EXPECT_TRUE(incidentKeyStore->encrypt(plaintext, 0, &encrypted));
+    std::string decrypted;
+    EXPECT_TRUE(incidentKeyStore->decrypt(encrypted, &decrypted));
+
+    EXPECT_FALSE(encrypted.empty());
+    EXPECT_EQ(plaintext, decrypted);
+}
+
+TEST_F(IncidentKeyStoreTest, test_encrypt_empty_hash) {
+    std::string hash = "";
+
+    std::string encrypted;
+    EXPECT_FALSE(incidentKeyStore->encrypt(hash, 0, &encrypted));
+
+    EXPECT_TRUE(encrypted.empty());
+}
+
+TEST_F(IncidentKeyStoreTest, test_decrypt_empty_hash) {
+    std::string hash = "";
+
+    std::string decrypted;
+    EXPECT_FALSE(incidentKeyStore->decrypt(hash, &decrypted));
+
+    EXPECT_TRUE(decrypted.empty());
+}
\ No newline at end of file
diff --git a/cmds/incidentd/tests/ProtoEncryption_test.cpp b/cmds/incidentd/tests/ProtoEncryption_test.cpp
new file mode 100644
index 0000000..6742e03
--- /dev/null
+++ b/cmds/incidentd/tests/ProtoEncryption_test.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Log.h"
+
+#include "cipher/ProtoEncryption.h"
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+#include "FdBuffer.h"
+#include "android/util/ProtoFileReader.h"
+
+using namespace android::os::incidentd;
+using android::sp;
+using std::string;
+using ::testing::Test;
+
+const std::string kTestPath = GetExecutableDirectory();
+const std::string kTestDataPath = kTestPath + "/testdata/";
+
+TEST(ProtoEncryptionTest, test_encrypt_decrypt) {
+    const std::string plaintextFile = kTestDataPath + "plaintext.txt";
+    const std::string encryptedFile = kTestDataPath + "encrypted.txt";
+    size_t msg1Size = 20 * 1024;
+
+    // Create a file with plain text.
+    {
+        unique_fd fd(
+                open(plaintextFile.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+        ASSERT_NE(fd.get(), -1);
+        string content;
+        content.resize(msg1Size, 'a');
+        WriteFully(fd, content.data(), msg1Size);
+    }
+
+    // Read the plain text and encrypted
+    {
+        unique_fd readFd(open(plaintextFile.c_str(), O_RDONLY | O_CLOEXEC));
+        unique_fd encryptedFd(
+                open(encryptedFile.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+
+        ASSERT_NE(readFd.get(), -1);
+        ASSERT_NE(encryptedFd.get(), -1);
+
+        sp<ProtoFileReader> reader = new ProtoFileReader(readFd.get());
+        ProtoEncryptor encryptor(reader);
+        EXPECT_TRUE(encryptor.encrypt() > msg1Size);
+
+        encryptor.flush(encryptedFd.get());
+    }
+
+    // Read the encrypted file, and decrypt
+    unique_fd encryptedFd(open(encryptedFile.c_str(), O_RDONLY | O_CLOEXEC));
+    ASSERT_NE(encryptedFd.get(), -1);
+    FdBuffer output;
+    sp<ProtoFileReader> reader2 = new ProtoFileReader(encryptedFd.get());
+    ProtoDecryptor decryptor(reader2, reader2->size());
+    decryptor.decryptAndFlush(&output);
+
+    auto decryptedReader = output.data()->read();
+
+    // Check the content.
+    int count = 0;
+    while (decryptedReader->hasNext()) {
+        if (decryptedReader->next() == 'a') {
+            count++;
+        }
+    }
+
+    EXPECT_EQ(msg1Size, count);
+}
\ No newline at end of file
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e66cd31..3898328 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -39,7 +39,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
-import android.media.MediaScannerConnection;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
@@ -8609,6 +8608,13 @@
      * fields, the identifier is <em>never</em> used for matching against an {@link IntentFilter};
      * it is as if the identifier has not been set on the Intent.
      *
+     * <p>This can be used, for example, to make this Intent unique from other Intents that
+     * are otherwise the same, for use in creating a {@link android.app.PendingIntent}.  (Be aware
+     * however that the receiver of the PendingIntent will see whatever you put in here.)  The
+     * structure of this string is completely undefined by the platform, however if you are going
+     * to be exposing identifier strings across different applications you may need to define
+     * your own structure if there is no central party defining the contents of this field.</p>
+     *
      * @param identifier The identifier for this Intent.  The contents of the string have no
      *                   meaning to the system, except whether they are exactly the same as
      *                   another identifier.
@@ -10181,6 +10187,9 @@
         if (mType != null) {
             proto.write(IntentProto.TYPE, mType);
         }
+        if (mIdentifier != null) {
+            proto.write(IntentProto.IDENTIFIER, mIdentifier);
+        }
         if (mFlags != 0) {
             proto.write(IntentProto.FLAG, "0x" + Integer.toHexString(mFlags));
         }
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 639335e..1838bab 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -45,8 +45,7 @@
             STATE_DISABLED,
             STATE_ENABLED,
             STATE_ENABLED_STATIC,
-            // @Deprecated STATE_TARGET_UPGRADING,
-            STATE_TARGET_IS_BEING_REPLACED,
+            // @Deprecated STATE_TARGET_IS_BEING_REPLACED,
             STATE_OVERLAY_IS_BEING_REPLACED,
     })
     /** @hide */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index abb68e7..5f3e057 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -87,8 +87,8 @@
     public static final boolean APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = true;
 
     /** {@hide} */
-    @SystemApi
     @TestApi
+    // STOPSHIP: Remove this once we get a Play prebuilt.
     public static boolean RESTRICTED_PERMISSIONS_ENABLED = false;
 
     /**
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 3ffc21d..04e8cf4 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -609,16 +609,17 @@
 
     /**
      * <p>The camera device supports capturing high-resolution images at &gt;= 20 frames per
-     * second, in at least the uncompressed YUV format, when post-processing settings are set
-     * to FAST. Additionally, maximum-resolution images can be captured at &gt;= 10 frames
-     * per second.  Here, 'high resolution' means at least 8 megapixels, or the maximum
-     * resolution of the device, whichever is smaller.</p>
+     * second, in at least the uncompressed YUV format, when post-processing settings are
+     * set to FAST. Additionally, all image resolutions less than 24 megapixels can be
+     * captured at &gt;= 10 frames per second. Here, 'high resolution' means at least 8
+     * megapixels, or the maximum resolution of the device, whichever is smaller.</p>
      * <p>More specifically, this means that a size matching the camera device's active array
      * size is listed as a supported size for the {@link android.graphics.ImageFormat#YUV_420_888 } format in either {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } or {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes },
      * with a minimum frame duration for that format and size of either &lt;= 1/20 s, or
-     * &lt;= 1/10 s, respectively; and the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry
-     * lists at least one FPS range where the minimum FPS is &gt;= 1 / minimumFrameDuration
-     * for the maximum-size YUV_420_888 format.  If that maximum size is listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes },
+     * &lt;= 1/10 s if the image size is less than 24 megapixels, respectively; and
+     * the {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES android.control.aeAvailableTargetFpsRanges} entry lists at least one FPS range
+     * where the minimum FPS is &gt;= 1 / minimumFrameDuration for the maximum-size
+     * YUV_420_888 format.  If that maximum size is listed in {@link android.hardware.camera2.params.StreamConfigurationMap#getHighResolutionOutputSizes },
      * then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at
      * least one resolution &gt;= 8 megapixels, with a minimum frame duration of &lt;= 1/20
      * s.</p>
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 996f997..bdba77c 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -838,8 +838,10 @@
      * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}
      * capability.  This does not include the stall duration, so for example, a JPEG or RAW16 output
      * resolution with a large stall duration but a minimum frame duration that's above 20 fps will
-     * still be listed in the regular {@link #getOutputSizes} list. All the sizes on this list are
-     * still guaranteed to operate at a rate of at least 10 fps, not including stall duration.</p>
+     * still be listed in the regular {@link #getOutputSizes} list. All the sizes on this list that
+     * are less than 24 megapixels are still guaranteed to operate at a rate of at least 10 fps,
+     * not including stall duration. Sizes on this list that are at least 24 megapixels are allowed
+     * to operate at less than 10 fps.</p>
      *
      * <p>For a device that does not support the BURST_CAPTURE capability, this list will be
      * {@code null}, since resolutions in the {@link #getOutputSizes} list are already not
diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java
index 5b67406..cf08b65 100644
--- a/core/java/android/net/UrlQuerySanitizer.java
+++ b/core/java/android/net/UrlQuerySanitizer.java
@@ -22,6 +22,8 @@
 import java.util.Locale;
 import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  *
@@ -837,15 +839,11 @@
      * @param string the escaped string
      * @return the unescaped string.
      */
+    private static final Pattern plusOrPercent = Pattern.compile("[+%]");
     public String unescape(String string) {
-        // Early exit if no escaped characters.
-        int firstEscape = string.indexOf('%');
-        if ( firstEscape < 0) {
-            firstEscape = string.indexOf('+');
-            if (firstEscape < 0) {
-                return string;
-            }
-        }
+        final Matcher matcher = plusOrPercent.matcher(string);
+        if (!matcher.find()) return string;
+        final int firstEscape = matcher.start();
 
         int length = string.length();
 
@@ -855,8 +853,7 @@
             char c = string.charAt(i);
             if (c == '+') {
                 c = ' ';
-            }
-            else if ( c == '%' && i + 2 < length) {
+            } else if (c == '%' && i + 2 < length) {
                 char c1 = string.charAt(i + 1);
                 char c2 = string.charAt(i + 2);
                 if (isHexDigit(c1) && isHexDigit(c2)) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 7d61bf6..2fff595 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -555,6 +555,18 @@
     }
 
     /**
+     * @hide
+     */
+    public static class WakeData {
+        public WakeData(long wakeTime, @WakeReason int wakeReason) {
+            this.wakeTime = wakeTime;
+            this.wakeReason = wakeReason;
+        }
+        public long wakeTime;
+        public @WakeReason int wakeReason;
+    }
+
+    /**
      * The value to pass as the 'reason' argument to reboot() to reboot into
      * recovery mode for tasks other than applying system updates, such as
      * doing factory resets.
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index d55489a..9661a08 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -203,4 +203,7 @@
 
     /** Returns whether there hasn't been a user activity event for the given number of ms. */
     public abstract boolean wasDeviceIdleFor(long ms);
+
+    /** Returns information about the last wakeup event. */
+    public abstract PowerManager.WakeData getLastWakeup();
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ac59101..24f42d4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11124,8 +11124,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
 
         /**
@@ -11134,8 +11132,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
 
         /**
@@ -11144,8 +11140,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
 
         /**
@@ -11155,8 +11149,6 @@
          * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
 
         /**
@@ -11185,8 +11177,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
 
         /**
@@ -11195,8 +11185,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
 
         /**
@@ -11205,8 +11193,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
 
         /**
@@ -11215,8 +11201,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
                 "captive_portal_other_fallback_urls";
 
@@ -11226,8 +11210,6 @@
          * by "@@,@@".
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
                 "captive_portal_fallback_probe_specs";
 
@@ -11238,8 +11220,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
 
         /**
@@ -11248,8 +11228,6 @@
          *
          * @hide
          */
-        @SystemApi
-        @TestApi
         public static final String CAPTIVE_PORTAL_USER_AGENT = "captive_portal_user_agent";
 
         /**
@@ -14712,6 +14690,18 @@
         public static final String TEXT_CLASSIFIER_ACTION_MODEL_PARAMS =
                 "text_classifier_action_model_params";
 
+        /**
+         * The amount of time to suppress "power-off" from the power button after the device has
+         * woken due to a gesture (lifting the phone).  Since users have learned to hit the power
+         * button immediately when lifting their device, it can cause the device to turn off if a
+         * gesture has just woken the device. This value tells us the milliseconds to wait after
+         * a gesture before "power-off" via power-button is functional again. A value of 0 is no
+         * delay, and reverts to the old behavior.
+         *
+         * @hide
+         */
+        public static final String POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE =
+                "power_button_suppression_delay_after_gesture_wake";
     }
 
     /**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 0051d01..bbd44c8 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -682,14 +682,6 @@
                     // Handle this hidden action separately
                     succeeded = handleClickableSpanActionUiThread(
                             target, virtualDescendantId, arguments);
-                } else if (action == R.id.accessibilityActionOutsideTouch) {
-                    // trigger ACTION_OUTSIDE to notify windows
-                    final long now = SystemClock.uptimeMillis();
-                    MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_OUTSIDE,
-                            0, 0, 0);
-                    event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-                    mViewRootImpl.dispatchInputEvent(event);
-                    succeeded = true;
                 } else {
                     AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                     if (provider != null) {
@@ -756,6 +748,33 @@
         }
     }
 
+    /**
+     * Notify outside touch event to the target window.
+     */
+    public void notifyOutsideTouchClientThread() {
+        final Message message = mHandler.obtainMessage();
+        message.what = PrivateHandler.MSG_NOTIFY_OUTSIDE_TOUCH;
+
+        // Don't care about pid and tid because there's no interrogating client for this message.
+        scheduleMessage(message, 0, 0, CONSIDER_REQUEST_PREPARERS);
+    }
+
+    private void notifyOutsideTouchUiThread() {
+        if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null
+                || mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) {
+            return;
+        }
+        final View root = mViewRootImpl.mView;
+        if (root != null && isShown(root)) {
+            // trigger ACTION_OUTSIDE to notify windows
+            final long now = SystemClock.uptimeMillis();
+            final MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_OUTSIDE,
+                    0, 0, 0);
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+            mViewRootImpl.dispatchInputEvent(event);
+        }
+    }
+
     private View findViewByAccessibilityId(int accessibilityId) {
         if (accessibilityId == AccessibilityNodeInfo.ROOT_ITEM_ID) {
             return mViewRootImpl.mView;
@@ -1328,6 +1347,8 @@
         private static final int FIRST_NO_ACCESSIBILITY_CALLBACK_MSG = 100;
         private static final int MSG_CLEAR_ACCESSIBILITY_FOCUS =
                 FIRST_NO_ACCESSIBILITY_CALLBACK_MSG + 1;
+        private static final int MSG_NOTIFY_OUTSIDE_TOUCH =
+                FIRST_NO_ACCESSIBILITY_CALLBACK_MSG + 2;
 
         public PrivateHandler(Looper looper) {
             super(looper);
@@ -1357,6 +1378,8 @@
                     return "MSG_APP_PREPARATION_TIMEOUT";
                 case MSG_CLEAR_ACCESSIBILITY_FOCUS:
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS";
+                case MSG_NOTIFY_OUTSIDE_TOUCH:
+                    return "MSG_NOTIFY_OUTSIDE_TOUCH";
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
@@ -1396,6 +1419,9 @@
                 case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
                     clearAccessibilityFocusUiThread();
                 } break;
+                case MSG_NOTIFY_OUTSIDE_TOUCH: {
+                    notifyOutsideTouchUiThread();
+                } break;
                 default:
                     throw new IllegalArgumentException("Unknown message type: " + type);
             }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7ad118e..e71c7ed 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8819,6 +8819,15 @@
                         .clearAccessibilityFocusClientThread();
             }
         }
+
+        @Override
+        public void notifyOutsideTouch() {
+            ViewRootImpl viewRootImpl = mViewRootImpl.get();
+            if (viewRootImpl != null && viewRootImpl.mView != null) {
+                viewRootImpl.getAccessibilityInteractionController()
+                        .notifyOutsideTouchClientThread();
+            }
+        }
     }
 
     private class SendWindowContentChangedAccessibilityEvent implements Runnable {
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 947ff05..deb0d2a 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -57,4 +57,6 @@
         int interrogatingPid, long interrogatingTid);
 
     void clearAccessibilityFocus();
+
+    void notifyOutsideTouch();
 }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index be66de2..ca2bc7f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -60,6 +60,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Path;
+import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
@@ -479,6 +480,28 @@
             if (isSendAction(target)) {
                 mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll);
             }
+
+            final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
+            final float defaultElevation = chooserHeader.getElevation();
+            final float chooserHeaderScrollElevation =
+                    getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation);
+
+            mAdapterView.setOnScrollListener(new AbsListView.OnScrollListener() {
+                public void onScrollStateChanged(AbsListView view, int scrollState) {
+                }
+
+                public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+                        int totalItemCount) {
+                    if (view.getChildCount() > 0) {
+                        if (firstVisibleItem > 0 || view.getChildAt(0).getTop() < 0) {
+                            chooserHeader.setElevation(chooserHeaderScrollElevation);
+                            return;
+                        }
+                    }
+
+                    chooserHeader.setElevation(defaultElevation);
+                }
+            });
         }
 
         if (DEBUG) {
@@ -1680,7 +1703,10 @@
 
     final class PlaceHolderTargetInfo extends NotSelectableTargetInfo {
         public Drawable getDisplayIcon() {
-            return getDrawable(R.drawable.resolver_icon_placeholder);
+            AnimatedVectorDrawable avd = (AnimatedVectorDrawable)
+                    getDrawable(R.drawable.chooser_direct_share_icon_placeholder);
+            avd.start(); // Start animation after generation
+            return avd;
         }
     }
 
@@ -1802,7 +1828,8 @@
             if (info == null) return null;
 
             // Now fetch app icon and raster with no badging even in work profile
-            Bitmap appIcon = makePresentationGetter(info).getIconBitmap();
+            Bitmap appIcon = makePresentationGetter(info).getIconBitmap(
+                    UserHandle.getUserHandleForUid(UserHandle.myUserId()));
 
             // Raster target drawable with appIcon as a badge
             SimpleIconFactory sif = SimpleIconFactory.obtain(ChooserActivity.this);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 2849f57..5e4918d 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -551,11 +551,11 @@
                     mAi.packageName);
         }
 
-        public Drawable getIcon() {
-            return new BitmapDrawable(mCtx.getResources(), getIconBitmap());
+        public Drawable getIcon(UserHandle userHandle) {
+            return new BitmapDrawable(mCtx.getResources(), getIconBitmap(userHandle));
         }
 
-        public Bitmap getIconBitmap() {
+        public Bitmap getIconBitmap(UserHandle userHandle) {
             Drawable dr = null;
             if (mHasSubstitutePermission) {
                 dr = getIconSubstituteInternal();
@@ -576,7 +576,7 @@
             }
 
             SimpleIconFactory sif = SimpleIconFactory.obtain(mCtx);
-            Bitmap icon = sif.createUserBadgedIconBitmap(dr, Process.myUserHandle());
+            Bitmap icon = sif.createUserBadgedIconBitmap(dr, userHandle);
             sif.recycle();
 
             return icon;
@@ -699,7 +699,8 @@
     }
 
     Drawable loadIconForResolveInfo(ResolveInfo ri) {
-        return makePresentationGetter(ri).getIcon();
+        // Load icons based on the current process. If in work profile icons should be badged.
+        return makePresentationGetter(ri).getIcon(Process.myUserHandle());
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/SimpleIconFactory.java b/core/java/com/android/internal/app/SimpleIconFactory.java
index 2484109..7a4e76f 100644
--- a/core/java/com/android/internal/app/SimpleIconFactory.java
+++ b/core/java/com/android/internal/app/SimpleIconFactory.java
@@ -43,7 +43,6 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.DrawableWrapper;
-import android.os.Process;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Pools.SynchronizedPool;
@@ -161,6 +160,7 @@
     /**
      * Creates bitmap using the source drawable and various parameters.
      * The bitmap is visually normalized with other icons and has enough spacing to add shadow.
+     * Note: this method has been modified from iconloaderlib to remove a profile diff check.
      *
      * @param icon                      source of the icon associated with a user that has no badge,
      *                                  likely user 0
@@ -186,7 +186,7 @@
         }
 
         final Bitmap result;
-        if (user != null && !Process.myUserHandle().equals(user)) {
+        if (user != null /* if modification from iconloaderlib */) {
             BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
             Drawable badged = mPm.getUserBadgedIcon(drawable, user);
             if (badged instanceof BitmapDrawable) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1fc7635..72f6c12 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -609,9 +609,7 @@
         int UPDATE_RADIO = 0x04;
         int UPDATE_BT = 0x08;
         int UPDATE_RPM = 0x10; // 16
-        int UPDATE_RAIL = 0x20; // 32
-        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM
-                | UPDATE_RAIL;
+        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
 
         Future<?> scheduleSync(String reason, int flags);
         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 8f8e4d8..f22b6cd 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -76,6 +76,7 @@
             in int notificationLocation, boolean modifiedBeforeSending);
     void onNotificationSettingsViewed(String key);
     void setSystemUiVisibility(int displayId, int vis, int mask, String cause);
+    void onNotificationBubbleChanged(String key, boolean isBubble);
 
     void onGlobalActionsShown();
     void onGlobalActionsHidden();
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 61d5031..b499981 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -256,6 +256,10 @@
         ssize_t offset;
         size_t size;
         sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
+        if (heap == NULL) {
+            ALOGV("copyAndPost: skipping null memory callback!");
+            return;
+        }
         ALOGV("copyAndPost: off=%zd, size=%zu", offset, size);
         uint8_t *heapBase = (uint8_t*)heap->base();
 
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 7052ed6..4fad239 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -1010,9 +1010,10 @@
         const float cx, const float cy, const float f,
         const int preCorrW, const int preCorrH, const int xMin, const int yMin) {
     undistort(x, y, distortion, cx, cy, f);
-    int xMax = xMin + preCorrW - 1;
-    int yMax = yMin + preCorrH - 1;
-    if (x < xMin || y < yMin || x > xMax || y > yMax) {
+    // xMin and yMin are inclusive, and xMax and yMax are exclusive.
+    int xMax = xMin + preCorrW;
+    int yMax = yMin + preCorrH;
+    if (x < xMin || y < yMin || x >= xMax || y >= yMax) {
         return false;
     }
     return true;
@@ -1976,7 +1977,6 @@
             if (entry3.count == 5) {
                 gotDistortion = true;
 
-
                 // Scale the distortion coefficients to create a zoom in warpped image so that all
                 // pixels are drawn within input image.
                 for (size_t i = 0; i < entry3.count; i++) {
@@ -1995,8 +1995,8 @@
                             preXMin, preYMin);
                 }
 
-                float m_x = std::fmaxf(preWidth-1 - cx, cx);
-                float m_y = std::fmaxf(preHeight-1 - cy, cy);
+                float m_x = std::fmaxf(preWidth - cx, cx);
+                float m_y = std::fmaxf(preHeight - cy, cy);
                 float m_sq = m_x*m_x + m_y*m_y;
                 float m = sqrtf(m_sq); // distance to farthest corner from optical center
                 float f_sq = f * f;
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d3f9196..2b471fe 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -163,7 +163,7 @@
       }
 
       // Generic idmap parameters
-      const char* argv[9];
+      const char* argv[10];
       int argc = 0;
       struct stat st;
 
@@ -203,6 +203,10 @@
         argv[argc++] = AssetManager::ODM_OVERLAY_DIR;
       }
 
+      if (stat(AssetManager::OEM_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::OEM_OVERLAY_DIR;
+      }
+
       // Finally, invoke idmap (if any overlay directory exists)
       if (argc > 5) {
         execv(AssetManager::IDMAP_BIN, (char* const*)argv);
@@ -241,6 +245,10 @@
     input_dirs.push_back(AssetManager::ODM_OVERLAY_DIR);
   }
 
+  if (stat(AssetManager::OEM_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::OEM_OVERLAY_DIR);
+  }
+
   if (input_dirs.empty()) {
     LOG(WARNING) << "no directories for idmap2 to scan";
     return env->NewObjectArray(0, g_stringClass, nullptr);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index a900294..ccadc7d 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -212,6 +212,10 @@
         return 0;
     }
 
+    if (convertPixelFormat(ANativeWindow_getFormat(surface.get())) == kUnknown_SkColorType) {
+        native_window_set_buffers_format(surface.get(), PIXEL_FORMAT_RGBA_8888);
+    }
+
     Rect dirtyRect(Rect::EMPTY_RECT);
     Rect* dirtyRectPtr = NULL;
 
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 77ebd02..fa5f931 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -104,6 +104,8 @@
   static const char* kProductServicesOverlayDir = "/product_services/overlay";
   static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
   static const char* kOdmOverlayDir = "/odm/overlay";
+  static const char* kSystemOemOverlayDir = "/system/oem/overlay";
+  static const char* kOemOverlayDir = "/oem/overlay";
   static const char* kApkSuffix = ".apk";
 
   if ((android::base::StartsWith(path, kOverlayDir)
@@ -114,7 +116,9 @@
        || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
        || android::base::StartsWith(path, kProductServicesOverlayDir)
        || android::base::StartsWith(path, kSystemOdmOverlayDir)
-       || android::base::StartsWith(path, kOdmOverlayDir))
+       || android::base::StartsWith(path, kOdmOverlayDir)
+       || android::base::StartsWith(path, kSystemOemOverlayDir)
+       || android::base::StartsWith(path, kOemOverlayDir))
       && android::base::EndsWith(path, kApkSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index c828cac..1ff7418 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -665,6 +665,15 @@
 
     //ACTION: Log result for each card's eligibility check
     ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686;
+
+    // ACTION: Share a Wi-Fi network by generating a QR code
+    ACTION_SETTINGS_SHARE_WIFI_QR_CODE = 1710;
+
+    // ACTION: Connect to a Wi-Fi network by scanning a QR code
+    ACTION_SETTINGS_ENROLL_WIFI_QR_CODE = 1711;
+
+    // ACTION: Share Wi-Fi hotspot by generating a QR code
+    ACTION_SETTINGS_SHARE_WIFI_HOTSPOT_QR_CODE = 1712;
 }
 
 /**
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
index 2de538d..014d71c 100644
--- a/core/proto/android/content/intent.proto
+++ b/core/proto/android/content/intent.proto
@@ -23,7 +23,7 @@
 import "frameworks/base/core/proto/android/os/patternmatcher.proto";
 import "frameworks/base/core/proto/android/privacy.proto";
 
-// Next Tag: 13
+// Next Tag: 14
 message IntentProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -62,6 +62,7 @@
     // UserHandle value (similar to user_id in other protos).
     optional int32 content_user_hint = 11;
     optional string selector = 12;
+    optional string identifier = 13 [ (.android.privacy).dest = DEST_EXPLICIT ];
 }
 
 // Next Tag: 11
diff --git a/core/res/res/drawable/chooser_direct_share_icon_placeholder.xml b/core/res/res/drawable/chooser_direct_share_icon_placeholder.xml
new file mode 100644
index 0000000..838cb49
--- /dev/null
+++ b/core/res/res/drawable/chooser_direct_share_icon_placeholder.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+                 xmlns:aapt="http://schemas.android.com/aapt">
+    <aapt:attr name="android:drawable">
+        <vector xmlns:android="http://schemas.android.com/apk/res/android"
+                xmlns:aapt="http://schemas.android.com/aapt"
+                android:width="36dp"
+                android:height="36dp"
+                android:viewportHeight="64"
+                android:viewportWidth="64">
+
+            <group android:name="background">
+                <path android:pathData="M0,0 L 64,0 64,64 0,64 z"
+                      android:fillColor="@color/chooser_gradient_background"/>
+            </group>
+
+            <!-- Gradient starts offscreen so it is not visible in the first frame before start -->
+            <group android:name="gradient" android:translateX="-128">
+                <path
+                    android:pathData="M0,0 L 128,0 128,128 0,128 z">
+                    <aapt:attr name="android:fillColor">
+                        <gradient
+                            android:type="linear"
+                            android:startX="0"
+                            android:endX="128"
+                            android:startY="0"
+                            android:endY="0">
+                            <item
+                                android:color="@android:color/transparent"
+                                android:offset="0.0" />
+                            <item
+                                android:color="@color/chooser_gradient_highlight"
+                                android:offset="0.5" />
+                            <item
+                                android:color="@android:color/transparent"
+                                android:offset="1.0" />
+                        </gradient>
+                    </aapt:attr>
+                </path>
+            </group>
+
+            <!-- Use a foregroud with a cutout shape matching direct share inset for appx applied
+                 shadow. Using clip-path is a more elegant solution but leaves awful jaggies around
+                 the path's shape. -->
+            <group android:name="cover">
+                <path android:fillColor="?attr/colorBackgroundFloating"
+                      android:pathData="M0,0 L64,0 L64,64 L0,64 L0,0 Z M59.0587325,42.453601 C60.3124932,39.2104785 61,35.6855272 61,32 C61,15.9837423 48.0162577,3 32,3 C15.9837423,3 3,15.9837423 3,32 C3,48.0162577 15.9837423,61 32,61 C35.6855272,61 39.2104785,60.3124932 42.453601,59.0587325 C44.3362195,60.2864794 46.5847839,61 49,61 C55.627417,61 61,55.627417 61,49 C61,46.5847839 60.2864794,44.3362195 59.0587325,42.453601 Z"/>
+            </group>
+        </vector>
+    </aapt:attr>
+
+    <!-- This AVD uses special properties so that once started it will loop infinitely with no
+         need for callbacks to restart. -->
+    <target android:name="gradient">
+        <aapt:attr name="android:animation">
+            <objectAnimator
+                android:duration="1700"
+                android:pathData="M -128,0 L 192,0"
+                android:propertyXName="translateX"
+                android:repeatMode="restart"
+                android:repeatCount="infinite"
+                android:startOffset="0">
+                <aapt:attr name="android:interpolator">
+                    <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
+                </aapt:attr>
+            </objectAnimator>
+        </aapt:attr>
+    </target>
+</animated-vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/resolver_icon_placeholder.xml b/core/res/res/drawable/resolver_icon_placeholder.xml
index 049cfee..7236fbe 100644
--- a/core/res/res/drawable/resolver_icon_placeholder.xml
+++ b/core/res/res/drawable/resolver_icon_placeholder.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
-    <solid android:color="#10000000"/>
+    <solid android:color="@color/chooser_gradient_background"/>
     <size android:width="36dp" android:height="36dp"/>
 </shape>
\ No newline at end of file
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 4d5e262..8727f4c 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -25,6 +25,7 @@
     android:id="@id/contentPanel">
 
     <RelativeLayout
+        android:id="@+id/chooser_header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alwaysShow="true"
@@ -62,11 +63,10 @@
         android:layout_height="match_parent"
         android:id="@+id/resolver_list"
         android:clipToPadding="false"
-        android:scrollbarStyle="outsideOverlay"
         android:background="?attr/colorBackgroundFloating"
+        android:scrollbars="none"
         android:listSelector="@color/transparent"
         android:divider="@null"
-        android:scrollIndicators="top"
         android:elevation="1dp"
         android:nestedScrollingEnabled="true"/>
 
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index 6aca49b..c5e72f0 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -30,4 +30,6 @@
     <color name="notification_material_background_color">@color/black</color>
 
     <color name="chooser_row_divider">@color/list_divider_color_dark</color>
+    <color name="chooser_gradient_background">@color/loading_gradient_background_color_dark</color>
+    <color name="chooser_gradient_highlight">@color/loading_gradient_highlight_color_dark</color>
 </resources>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index ef26cd7..048f341 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -216,4 +216,6 @@
     <color name="default_magnifier_color_overlay">#00FFFFFF</color>
 
     <color name="chooser_row_divider">@color/list_divider_color_light</color>
+    <color name="chooser_gradient_background">@color/loading_gradient_background_color_light</color>
+    <color name="chooser_gradient_highlight">@color/loading_gradient_highlight_color_light</color>
 </resources>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 5af3c2a..112f98e 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -48,4 +48,8 @@
 
     <color name="list_divider_color_light">#ffdadce0</color>
     <color name="list_divider_color_dark">#85ffffff</color>
+    <color name="loading_gradient_background_color_dark">#2D3033</color>
+    <color name="loading_gradient_background_color_light">#DADCE0</color>
+    <color name="loading_gradient_highlight_color_dark">#3C4043</color>
+    <color name="loading_gradient_highlight_color_light">#F1F3F4</color>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index b81db15..d6ec414 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -51,18 +51,23 @@
          that just start below the notch. -->
     <dimen name="display_cutout_touchable_region_size">12dp</dimen>
 
-    <!-- EXPERIMENT BEGIN -->
     <!-- Height of the bottom navigation bar frame; this is different than navigation_bar_height
          where that is the height reported to all the other windows to resize themselves around the
          navigation bar window but navigation_bar_frame_height is reported to SystemUI navigation
          bar view's window -->
     <dimen name="navigation_bar_frame_height">@dimen/navigation_bar_height</dimen>
+    <!-- Height of the bottom navigation bar frame in landscape -->
+    <dimen name="navigation_bar_frame_height_landscape">@dimen/navigation_bar_frame_height</dimen>
     <!-- Width of the left/right navigation bar frame; this is different than navigation_bar_width
          where that is the width reported to all the other windows to resize themselves around the
          navigation bar window but navigation_bar_frame_width is reported to SystemUI navigation
          bar view's window -->
     <dimen name="navigation_bar_frame_width">@dimen/navigation_bar_width</dimen>
-    <!-- EXPERIMENT END-->
+
+    <!-- The height of the navigation gesture area; if the size is larger than the navigation bar
+        frame width/height, then the difference is the spacing from the navigation bar window to
+        the area that detects gestures. -->
+    <dimen name="navigation_bar_gesture_height">@dimen/navigation_bar_frame_height</dimen>
 
     <!-- Height of the bottom navigation / system bar in car mode. -->
     <dimen name="navigation_bar_height_car_mode">96dp</dimen>
@@ -729,5 +734,6 @@
     <dimen name="resolver_icon_size">42dp</dimen>
     <dimen name="resolver_badge_size">18dp</dimen>
     <dimen name="chooser_target_width">90dp</dimen>
+    <dimen name="chooser_header_scroll_elevation">4dp</dimen>
     <dimen name="chooser_max_collapsed_height">288dp</dimen>
 </resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index ce7995a..2b0c86b 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -185,9 +185,6 @@
     <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_HIDE_TOOLTIP}. -->
     <item type="id" name="accessibilityActionHideTooltip" />
 
-  <!-- Accessibility action to notify a window there is an outside touch. -->
-  <item type="id" name="accessibilityActionOutsideTouch" />
-
   <!-- A tag used to save the view added to a transition overlay -->
   <item type="id" name="transition_overlay_view_tag" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4bd2cc75..ef834aa 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1507,6 +1507,13 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=90] -->
     <string name="permdesc_useFaceAuthentication">Allows the app to use face authentication hardware for authentication</string>
 
+    <!-- Notification name shown when the system requires the user to re-enroll their face. [CHAR LIMIT=NONE] -->
+    <string name="face_recalibrate_notification_name">Face Authentication</string>
+    <!-- Notification title shown when the system requires the user to re-enroll their face. [CHAR LIMIT=NONE] -->
+    <string name="face_recalibrate_notification_title">Re-enroll your face</string>
+    <!-- Notification content shown when the system requires the user to re-enroll their face. [CHAR LIMIT=NONE] -->
+    <string name="face_recalibrate_notification_content">To improve recognition, please re-enroll your face</string>
+
     <!-- Message shown during face acquisition when the face cannot be recognized [CHAR LIMIT=50] -->
     <string name="face_acquired_insufficient">Couldn\u2019t capture accurate face data. Try again.</string>
     <!-- Message shown during face acquisition when the image is too bright [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 186b84c..470c9ed 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -245,7 +245,6 @@
   <java-symbol type="id" name="selection_end_handle" />
   <java-symbol type="id" name="insertion_handle" />
   <java-symbol type="id" name="accessibilityActionClickOnClickableSpan" />
-  <java-symbol type="id" name="accessibilityActionOutsideTouch" />
   <java-symbol type="id" name="camera" />
   <java-symbol type="id" name="mic" />
   <java-symbol type="id" name="overlay" />
@@ -1747,6 +1746,8 @@
   <java-symbol type="dimen" name="navigation_bar_height_landscape" />
   <java-symbol type="dimen" name="navigation_bar_width" />
   <java-symbol type="dimen" name="navigation_bar_frame_height" />
+  <java-symbol type="dimen" name="navigation_bar_frame_height_landscape" />
+  <java-symbol type="dimen" name="navigation_bar_gesture_height" />
   <java-symbol type="dimen" name="navigation_bar_frame_width" />
   <java-symbol type="dimen" name="navigation_bar_height_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
@@ -2531,6 +2532,9 @@
   <java-symbol type="bool" name="config_fingerprintSupportsGestures"/>
 
   <!-- Face authentication messages -->
+  <java-symbol type="string" name="face_recalibrate_notification_name" />
+  <java-symbol type="string" name="face_recalibrate_notification_title" />
+  <java-symbol type="string" name="face_recalibrate_notification_content" />
   <java-symbol type="string" name="face_error_unable_to_process" />
   <java-symbol type="string" name="face_error_hw_not_available" />
   <java-symbol type="string" name="face_error_no_space" />
@@ -2784,6 +2788,8 @@
   <java-symbol type="dimen" name="chooser_preview_image_border"/>
   <java-symbol type="dimen" name="chooser_max_collapsed_height" />
   <java-symbol type="layout" name="chooser_grid" />
+  <java-symbol type="id" name="chooser_header" />
+  <java-symbol type="dimen" name="chooser_header_scroll_elevation" />
   <java-symbol type="layout" name="chooser_grid_preview_text" />
   <java-symbol type="layout" name="chooser_grid_preview_image" />
   <java-symbol type="layout" name="chooser_grid_preview_file" />
@@ -3760,4 +3766,8 @@
   <java-symbol type="drawable" name="perm_group_camera" />
   <java-symbol type="drawable" name="perm_group_location" />
   <java-symbol type="drawable" name="perm_group_microphone" />
+
+  <java-symbol type="drawable" name="chooser_direct_share_icon_placeholder" />
+  <java-symbol type="color" name="chooser_gradient_background" />
+  <java-symbol type="color" name="chooser_gradient_highlight" />
 </resources>
diff --git a/core/tests/coretests/res/values/overlayable_icons_test.xml b/core/tests/coretests/res/values/overlayable_icons_test.xml
new file mode 100644
index 0000000..9bc46de
--- /dev/null
+++ b/core/tests/coretests/res/values/overlayable_icons_test.xml
@@ -0,0 +1,67 @@
+<!--
+   Copyright (C) 2019 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<resources>
+  <!-- overlayable_icons references all of the drawables in this package
+       that are being overlayed by resource overlays. If you remove/rename
+       any of these resources, you must also change the resource overlay icons.-->
+  <array name="overlayable_icons">
+    <item>@*android:drawable/ic_audio_alarm</item>
+    <item>@*android:drawable/ic_audio_alarm_mute</item>
+    <item>@*android:drawable/ic_bluetooth_share_icon</item>
+    <item>@*android:drawable/ic_bt_headphones_a2dp</item>
+    <item>@*android:drawable/ic_bt_headset_hfp</item>
+    <item>@*android:drawable/ic_bt_hearing_aid</item>
+    <item>@*android:drawable/ic_bt_laptop</item>
+    <item>@*android:drawable/ic_bt_network_pan</item>
+    <item>@*android:drawable/ic_bt_pointing_hid</item>
+    <item>@*android:drawable/ic_expand_more</item>
+    <item>@*android:drawable/ic_file_copy</item>
+    <item>@*android:drawable/ic_info_outline_24</item>
+    <item>@*android:drawable/ic_lock</item>
+    <item>@*android:drawable/ic_lock_bugreport</item>
+    <item>@*android:drawable/ic_lock_open</item>
+    <item>@*android:drawable/ic_lock_power_off</item>
+    <item>@*android:drawable/ic_lockscreen_ime</item>
+    <item>@*android:drawable/ic_mode_edit</item>
+    <item>@*android:drawable/ic_phone</item>
+    <item>@*android:drawable/ic_qs_airplane</item>
+    <item>@*android:drawable/ic_qs_auto_rotate</item>
+    <item>@*android:drawable/ic_qs_bluetooth</item>
+    <item>@*android:drawable/ic_qs_dnd</item>
+    <item>@*android:drawable/ic_qs_flashlight</item>
+    <item>@*android:drawable/ic_qs_night_display_on</item>
+    <item>@*android:drawable/ic_restart</item>
+    <item>@*android:drawable/ic_screenshot</item>
+    <item>@*android:drawable/ic_settings_bluetooth</item>
+    <item>@*android:drawable/ic_signal_location</item>
+    <item>@*android:drawable/ic_wifi_signal_0</item>
+    <item>@*android:drawable/ic_wifi_signal_1</item>
+    <item>@*android:drawable/ic_wifi_signal_2</item>
+    <item>@*android:drawable/ic_wifi_signal_3</item>
+    <item>@*android:drawable/ic_wifi_signal_4</item>
+    <item>@*android:drawable/perm_group_activity_recognition</item>
+    <item>@*android:drawable/perm_group_call_log</item>
+    <item>@*android:drawable/perm_group_camera</item>
+    <item>@*android:drawable/perm_group_contacts</item>
+    <item>@*android:drawable/perm_group_location</item>
+    <item>@*android:drawable/perm_group_microphone</item>
+    <item>@*android:drawable/perm_group_phone_calls</item>
+    <item>@*android:drawable/perm_group_sensors</item>
+    <item>@*android:drawable/perm_group_sms</item>
+    <item>@*android:drawable/perm_group_storage</item>
+    <item>@*android:drawable/perm_group_visual</item>
+  </array>
+</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index a853121..f4d3c81 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -392,6 +392,7 @@
                     Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS,
                     Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
                     Settings.Global.POLICY_CONTROL,
+                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
                     Settings.Global.POWER_MANAGER_CONSTANTS,
                     Settings.Global.PREFERRED_NETWORK_MODE,
                     Settings.Global.PRIVATE_DNS_DEFAULT_MODE,
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index c8b361b..6d20ec3 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -596,8 +596,8 @@
                 final Font font = mFontBuilder.build();
                 final String key = mAssetManager == null ? null : createAssetUid(
                         mAssetManager, mPath, font.getTtcIndex(), font.getAxes(),
-                        font.getStyle().getWeight(), font.getStyle().getSlant(),
-                        mFallbackFamilyName);
+                        mWeight, mItalic,
+                        mFallbackFamilyName == null ? DEFAULT_FAMILY : mFallbackFamilyName);
                 if (key != null) {
                     // Dynamic cache lookup is only for assets.
                     synchronized (sDynamicCacheLock) {
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 21609d3..4755cb8 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -76,6 +76,7 @@
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
 const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
 const char* AssetManager::ODM_OVERLAY_DIR = "/odm/overlay";
+const char* AssetManager::OEM_OVERLAY_DIR = "/oem/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index a015eab..66fba26b 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -63,6 +63,7 @@
     static const char* PRODUCT_OVERLAY_DIR;
     static const char* PRODUCT_SERVICES_OVERLAY_DIR;
     static const char* ODM_OVERLAY_DIR;
+    static const char* OEM_OVERLAY_DIR;
     /*
      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
      * APKs in VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 7cb241d..1b638c1 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -126,6 +126,10 @@
             SkGraphics::SetFontCacheLimit(mMaxCpuFontCacheBytes);
             break;
     }
+
+    // We must sync the cpu to make sure deletions of resources still queued up on the GPU actually
+    // happen.
+    mGrContext->flush(kSyncCpu_GrFlushFlag, 0, nullptr);
 }
 
 void CacheManager::trimStaleResources() {
diff --git a/libs/hwui/tests/unit/CommonPoolTests.cpp b/libs/hwui/tests/unit/CommonPoolTests.cpp
index 70a5f5a..da6a260 100644
--- a/libs/hwui/tests/unit/CommonPoolTests.cpp
+++ b/libs/hwui/tests/unit/CommonPoolTests.cpp
@@ -36,7 +36,9 @@
     EXPECT_TRUE(ran) << "Failed to flip atomic after 1 second";
 }
 
-TEST(CommonPool, threadCount) {
+// test currently relies on timings, which
+// makes it flaky. Disable for now
+TEST(DISABLED_CommonPool, threadCount) {
     std::set<pid_t> threads;
     std::array<std::future<pid_t>, 64> futures;
     for (int i = 0; i < futures.size(); i++) {
@@ -93,7 +95,9 @@
     EXPECT_NE(gettid(), tid1);
 }
 
-TEST(CommonPool, fullQueue) {
+// Test currently relies on timings
+// which makes it flaky, disable for now
+TEST(DISABLED_CommonPool, fullQueue) {
     std::mutex lock;
     std::condition_variable fence;
     bool signaled = false;
@@ -179,4 +183,4 @@
     }
     CommonPool::waitForIdle();
     ASSERT_EQ(0, ObjectTracker::count());
-}
\ No newline at end of file
+}
diff --git a/libs/protoutil/src/ProtoFileReader.cpp b/libs/protoutil/src/ProtoFileReader.cpp
index bbb1fe3..c7f1129 100644
--- a/libs/protoutil/src/ProtoFileReader.cpp
+++ b/libs/protoutil/src/ProtoFileReader.cpp
@@ -99,6 +99,7 @@
         // Shouldn't get to here.  Always call hasNext() before calling next().
         return 0;
     }
+    mPos++;
     return mBuffer[mOffset++];
 }
 
@@ -130,6 +131,7 @@
         const size_t chunk =
                 mMaxOffset - mOffset > amt ? amt : mMaxOffset - mOffset;
         mOffset += chunk;
+        mPos += chunk;
         amt -= chunk;
     }
 }
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index badffd1..36fe8da 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -16,12 +16,8 @@
 
 package android.location;
 
-import android.annotation.IntDef;
 import android.annotation.SystemApi;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * A container of supported GNSS chipset capabilities.
  *
@@ -29,53 +25,61 @@
  */
 @SystemApi
 public final class GnssCapabilities {
-    /** The GNSS chipset supports low power mode. */
-    public static final int LOW_POWER_MODE                                              = 0;
-
-    /** The GNSS chipset supports blacklisting satellites. */
-    public static final int SATELLITE_BLACKLIST                                         = 1;
-
-    /** The GNSS chipset supports geofencing. */
-    public static final int GEOFENCING                                                  = 2;
-
-    /** The GNSS chipset supports measurements.*/
-    public static final int MEASUREMENTS                                                = 3;
-
-    /** The GNSS chipset supports navigation messages. */
-    public static final int NAV_MESSAGES                                                = 4;
-
-    /** The GNSS chipset supports measurement corrections. */
-    public static final int MEASUREMENT_CORRECTIONS                                     = 5;
-
-    /** The GNSS chipset supports line-of-sight satellite identification measurement corrections. */
-    public static final int MEASUREMENT_CORRECTIONS_LOS_SATS                            = 6;
-
-    /** The GNSS chipset supports per satellite excess-path-length measurement corrections. */
-    public static final int MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH                  = 7;
-
-    /** The GNSS chipset supports reflecting planes measurement corrections. */
-    public static final int MEASUREMENT_CORRECTIONS_REFLECTING_PLANE                    = 8;
-
-    private static final int MIN_CAPABILITY = 0;
-    private static final int MAX_CAPABILITY = MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
-
     /**
-     * GNSS capability.
+     * Bit mask indicating GNSS chipset supports low power mode.
      * @hide
      */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            LOW_POWER_MODE,
-            SATELLITE_BLACKLIST,
-            GEOFENCING,
-            MEASUREMENTS,
-            NAV_MESSAGES,
-            MEASUREMENT_CORRECTIONS,
-            MEASUREMENT_CORRECTIONS_LOS_SATS,
-            MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH,
-            MEASUREMENT_CORRECTIONS_REFLECTING_PLANE
-    })
-    public @interface Capability {}
+    public static final long LOW_POWER_MODE                                     = 1L << 0;
+
+    /**
+     * Bit mask indicating GNSS chipset supports blacklisting satellites.
+     * @hide
+     */
+    public static final long SATELLITE_BLACKLIST                                = 1L << 1;
+
+    /**
+     * Bit mask indicating GNSS chipset supports geofencing.
+     * @hide
+     */
+    public static final long GEOFENCING                                         = 1L << 2;
+
+    /**
+     * Bit mask indicating GNSS chipset supports measurements.
+     * @hide
+     */
+    public static final long MEASUREMENTS                                       = 1L << 3;
+
+    /**
+     * Bit mask indicating GNSS chipset supports navigation messages.
+     * @hide
+     */
+    public static final long NAV_MESSAGES                                       = 1L << 4;
+
+    /**
+     * Bit mask indicating GNSS chipset supports measurement corrections.
+     * @hide
+     */
+    public static final long MEASUREMENT_CORRECTIONS                            = 1L << 5;
+
+    /**
+     * Bit mask indicating GNSS chipset supports line-of-sight satellite identification
+     * measurement corrections.
+     * @hide
+     */
+    public static final long MEASUREMENT_CORRECTIONS_LOS_SATS                   = 1L << 6;
+
+    /**
+     * Bit mask indicating GNSS chipset supports per satellite excess-path-length
+     * measurement corrections.
+     * @hide
+     */
+    public static final long MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH         = 1L << 7;
+
+    /**
+     * Bit mask indicating GNSS chipset supports reflecting planes measurement corrections.
+     * @hide
+     */
+    public static final long MEASUREMENT_CORRECTIONS_REFLECTING_PLANE           = 1L << 8;
 
     /** @hide */
     public static final long INVALID_CAPABILITIES = -1;
@@ -93,60 +97,94 @@
     }
 
     /**
-     * Returns {@code true} if the {@code capability} is supported by the GNSS implementation.
+     * Returns {@code true} if GNSS chipset supports low power mode, {@code false} otherwise.
      */
-    public boolean hasCapability(@Capability int capability) {
-        return isValidCapability(capability) && (mGnssCapabilities & (1 << capability)) != 0;
+    public boolean hasLowPowerMode() {
+        return hasCapability(LOW_POWER_MODE);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports blacklisting satellites, {@code false}
+     * otherwise.
+     */
+    public boolean hasSatelliteBlacklist() {
+        return hasCapability(SATELLITE_BLACKLIST);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports geofencing, {@code false} otherwise.
+     */
+    public boolean hasGeofencing() {
+        return hasCapability(GEOFENCING);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports measurements, {@code false} otherwise.
+     */
+    public boolean hasMeasurements() {
+        return hasCapability(MEASUREMENTS);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports navigation messages, {@code false} otherwise.
+     */
+    public boolean hasNavMessages() {
+        return hasCapability(NAV_MESSAGES);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports measurement corrections, {@code false}
+     * otherwise.
+     */
+    public boolean hasMeasurementCorrections() {
+        return hasCapability(MEASUREMENT_CORRECTIONS);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports line-of-sight satellite identification
+     * measurement corrections, {@code false} otherwise.
+     */
+    public boolean hasMeasurementCorrectionsLosSats() {
+        return hasCapability(MEASUREMENT_CORRECTIONS_LOS_SATS);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports per satellite excess-path-length measurement
+     * corrections, {@code false} otherwise.
+     */
+    public boolean hasMeasurementCorrectionsExcessPathLength() {
+        return hasCapability(MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH);
+    }
+
+    /**
+     * Returns {@code true} if GNSS chipset supports reflecting planes measurement corrections,
+     * {@code false} otherwise.
+     */
+    public boolean hasMeasurementCorrectionsReflectingPane() {
+        return hasCapability(MEASUREMENT_CORRECTIONS_REFLECTING_PLANE);
     }
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder("GnssCapabilities: (");
-        int capability = 0;
-        boolean addSeparator = false;
-        long gnssCapabilities = mGnssCapabilities;
-        while (gnssCapabilities != 0) {
-            if ((gnssCapabilities & 1) != 0) {
-                if (addSeparator) {
-                    sb.append(' ');
-                } else {
-                    addSeparator = true;
-                }
-                sb.append(toStringCapability(capability));
-            }
-            gnssCapabilities >>= 1;
-            ++capability;
+        StringBuilder sb = new StringBuilder("GnssCapabilities: ( ");
+        if (hasLowPowerMode()) sb.append("LOW_POWER_MODE ");
+        if (hasSatelliteBlacklist()) sb.append("SATELLITE_BLACKLIST ");
+        if (hasGeofencing()) sb.append("GEOFENCING ");
+        if (hasMeasurements()) sb.append("MEASUREMENTS ");
+        if (hasNavMessages()) sb.append("NAV_MESSAGES ");
+        if (hasMeasurementCorrections()) sb.append("MEASUREMENT_CORRECTIONS ");
+        if (hasMeasurementCorrectionsLosSats()) sb.append("MEASUREMENT_CORRECTIONS_LOS_SATS ");
+        if (hasMeasurementCorrectionsExcessPathLength()) {
+            sb.append("MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH ");
+        }
+        if (hasMeasurementCorrectionsReflectingPane()) {
+            sb.append("MEASUREMENT_CORRECTIONS_REFLECTING_PLANE ");
         }
         sb.append(")");
         return sb.toString();
     }
 
-    private boolean isValidCapability(@Capability int capability) {
-        return capability >= MIN_CAPABILITY && capability <= MAX_CAPABILITY;
-    }
-
-    private static String toStringCapability(@Capability int capability) {
-        switch (capability) {
-            case LOW_POWER_MODE:
-                return "LOW_POWER_MODE";
-            case SATELLITE_BLACKLIST:
-                return "SATELLITE_BLACKLIST";
-            case GEOFENCING:
-                return "GEOFENCING";
-            case MEASUREMENTS:
-                return "MEASUREMENTS";
-            case NAV_MESSAGES:
-                return "NAV_MESSAGES";
-            case MEASUREMENT_CORRECTIONS:
-                return "MEASUREMENT_CORRECTIONS";
-            case MEASUREMENT_CORRECTIONS_LOS_SATS:
-                return "MEASUREMENT_CORRECTIONS_LOS_SATS";
-            case MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH:
-                return "MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH";
-            case MEASUREMENT_CORRECTIONS_REFLECTING_PLANE:
-                return "MEASUREMENT_CORRECTIONS_REFLECTING_PLANE";
-            default:
-                return "Unknown(" + capability + ")";
-        }
+    private boolean hasCapability(long capability) {
+        return (mGnssCapabilities & capability) == capability;
     }
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index af60e3c..7a17505 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1986,17 +1986,19 @@
     }
 
     /**
-     * Returns the supported capabilities of the GNSS chipset or {@code null} if there is an error
-     * in obtaining the capabilities.
+     * Returns the supported capabilities of the GNSS chipset.
+     *
+     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present.
      *
      * @hide
      */
     @SystemApi
-    public @Nullable GnssCapabilities getGnssCapabilities() {
+    @RequiresPermission(ACCESS_FINE_LOCATION)
+    public @NonNull GnssCapabilities getGnssCapabilities() {
         try {
             long gnssCapabilities = mGnssMeasurementCallbackTransport.getGnssCapabilities();
             if (gnssCapabilities == GnssCapabilities.INVALID_CAPABILITIES) {
-                return null;
+                gnssCapabilities = 0L;
             }
             return GnssCapabilities.of(gnssCapabilities);
         } catch (RemoteException e) {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 79d8be1..3500475 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -414,18 +414,25 @@
     /**
      * Gets the additional session information which was set when the session was created.
      *
-     * @return The additional session information
+     * @return The additional session information, or {@link Bundle#EMPTY} if not set.
      */
-    @Nullable
+    @NonNull
     public Bundle getSessionInfo() {
-        if (mSessionInfo == null) {
-            try {
-                mSessionInfo = mSessionBinder.getSessionInfo();
-            } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in getSessionInfo.", e);
-            }
+        if (mSessionInfo != null) {
+            return new Bundle(mSessionInfo);
         }
-        return mSessionInfo;
+
+        // Get info from the connected session.
+        try {
+            mSessionInfo = mSessionBinder.getSessionInfo();
+        } catch (RemoteException e) {
+            Log.d(TAG, "Dead object in getSessionInfo.", e);
+        }
+
+        if (mSessionInfo == null) {
+            mSessionInfo = Bundle.EMPTY;
+        }
+        return new Bundle(mSessionInfo);
     }
 
     /**
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index d07052b..7ee2f0a 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -411,7 +411,15 @@
 
     Region region;
     for (uint32_t i = 0; i < count; ++i) {
-        region.merge(static_cast<const Rect&>(rects[i]));
+        region.orSelf(static_cast<const Rect&>(rects[i]));
+    }
+
+    // Hardware composer interprets a DamageRegion with a single Rect of {0,0,0,0} to be an
+    // undamaged region and {0,0,-1,-1} to be a fully damaged buffer. This is a confusing
+    // distinction for a public api. Instead, default both cases to be a fully damaged buffer.
+    if (count == 1 && region.getBounds().isEmpty()) {
+        transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION);
+        return;
     }
 
     transaction->setSurfaceDamageRegion(surfaceControl, region);
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index 9a074dd..728a239a 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -74,17 +74,21 @@
         android:layout_height="match_parent"
         android:layout="@layout/car_fullscreen_user_switcher"/>
 
-    <include layout="@layout/status_bar_expanded"
+    <include layout="@layout/notification_center_activity"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginBottom="@dimen/navigation_bar_height"
+        android:visibility="invisible"/>
+
+    <include layout="@layout/headsup_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:visibility="invisible"/>
 
-    <include layout="@layout/notification_center_activity"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:layout_marginBottom="112dp"
-             android:visibility="invisible"
-    />
+    <include layout="@layout/status_bar_expanded"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible"/>
 
     <com.android.systemui.statusbar.ScrimView
         android:id="@+id/scrim_in_front"
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index ae99126..8f8fd11 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -23,6 +23,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.car.drivingstate.CarDrivingStateEvent;
+import android.content.Context;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -38,10 +39,13 @@
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.car.notification.CarHeadsUpNotificationManager;
 import com.android.car.notification.CarNotificationListener;
 import com.android.car.notification.CarNotificationView;
 import com.android.car.notification.CarUxRestrictionManagerWrapper;
+import com.android.car.notification.HeadsUpEntry;
 import com.android.car.notification.NotificationClickHandlerFactory;
+import com.android.car.notification.NotificationDataManager;
 import com.android.car.notification.NotificationViewController;
 import com.android.car.notification.PreprocessingManager;
 import com.android.internal.statusbar.RegisterStatusBarResult;
@@ -407,8 +411,13 @@
         CarNotificationListener carNotificationListener = new CarNotificationListener();
         CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper =
                 new CarUxRestrictionManagerWrapper();
+        NotificationDataManager notificationDataManager = new NotificationDataManager();
+        CarHeadsUpNotificationManager carHeadsUpNotificationManager =
+                new CarSystemUIHeadsUpNotificationManager(mContext, clickHandlerFactory,
+                        notificationDataManager);
+
         carNotificationListener.registerAsSystemService(mContext, carUxRestrictionManagerWrapper,
-                clickHandlerFactory);
+                carHeadsUpNotificationManager, notificationDataManager);
 
         mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view);
         View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane);
@@ -1093,4 +1102,48 @@
             super.onLongPress(e);
         }
     }
+
+    /**
+     * SystemUi version onf the notification manager that overrides methods such that the
+     * notifications end up in the status bar layouts instead of a standalone window.
+     */
+    private class CarSystemUIHeadsUpNotificationManager extends CarHeadsUpNotificationManager {
+
+        CarSystemUIHeadsUpNotificationManager(Context context,
+                NotificationClickHandlerFactory clickHandlerFactory,
+                NotificationDataManager notificationDataManager) {
+            super(context, clickHandlerFactory, notificationDataManager);
+        }
+
+        @Override
+        protected View createHeadsUpPanel() {
+            // In SystemUi the view is already in the window so just return a reference.
+            return mStatusBarWindow.findViewById(R.id.notification_headsup);
+        }
+
+        @Override
+        protected void addHeadsUpPanelToDisplay() {
+            // Set the panel initial state to invisible
+            mHeadsUpPanel.setVisibility(View.INVISIBLE);
+        }
+
+        @Override
+        protected void setHeadsUpVisible() {
+            super.setHeadsUpVisible();
+            if (mHeadsUpPanel.getVisibility() == View.VISIBLE) {
+                mStatusBarWindowController.setHeadsUpShowing(true);
+                mStatusBarWindowController.setForceStatusBarVisible(true);
+            }
+        }
+
+        @Override
+        protected void removeNotificationFromPanel(HeadsUpEntry currentHeadsUpNotification) {
+            super.removeNotificationFromPanel(currentHeadsUpNotification);
+            // If the panel ended up empty and hidden we can remove it from SystemUi
+            if (mHeadsUpPanel.getVisibility() != View.VISIBLE) {
+                mStatusBarWindowController.setHeadsUpShowing(false);
+                mStatusBarWindowController.setForceStatusBarVisible(false);
+            }
+        }
+    }
 }
diff --git a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
index 52e54f9..69e91d1 100644
--- a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
+++ b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.provider.DeviceConfig;
 import android.service.watchdog.ExplicitHealthCheckService;
 import android.service.watchdog.PackageInfo;
 import android.util.Log;
@@ -27,6 +28,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Routes explicit health check requests to the appropriate {@link ExplicitHealthChecker}.
@@ -36,6 +38,10 @@
     // TODO: Add build dependency on NetworkStack stable AIDL so we can stop hard coding class name
     private static final String NETWORK_STACK_CONNECTOR_CLASS =
             "android.net.INetworkStackConnector";
+    private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
+            "watchdog_request_timeout_millis";
+    private static final long DEFAULT_REQUEST_TIMEOUT_MILLIS =
+            TimeUnit.HOURS.toMillis(1);
     // Modified only #onCreate, using concurrent collection to ensure thread visibility
     private final Map<String, ExplicitHealthChecker> mSupportedCheckers = new ConcurrentHashMap<>();
 
@@ -70,8 +76,17 @@
     @Override
     public List<PackageInfo> onGetSupportedPackages() {
         List<PackageInfo> packages = new ArrayList<>();
+        long requestTimeoutMillis = DeviceConfig.getLong(
+                DeviceConfig.NAMESPACE_ROLLBACK,
+                PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
+                DEFAULT_REQUEST_TIMEOUT_MILLIS);
+        if (requestTimeoutMillis <= 0) {
+            requestTimeoutMillis = DEFAULT_REQUEST_TIMEOUT_MILLIS;
+        }
         for (ExplicitHealthChecker checker : mSupportedCheckers.values()) {
-            packages.add(checker.getSupportedPackage());
+            PackageInfo pkg = new PackageInfo(checker.getSupportedPackageName(),
+                    requestTimeoutMillis);
+            packages.add(pkg);
         }
         return packages;
     }
@@ -87,7 +102,7 @@
         while (it.hasNext()) {
             ExplicitHealthChecker checker = it.next();
             if (checker.isPending()) {
-                packages.add(checker.getSupportedPackage().getPackageName());
+                packages.add(checker.getSupportedPackageName());
             }
         }
         return packages;
diff --git a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthChecker.java b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthChecker.java
index c51be88..a982d52 100644
--- a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthChecker.java
+++ b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthChecker.java
@@ -16,8 +16,6 @@
 
 package android.ext.services.watchdog;
 
-import android.service.watchdog.PackageInfo;
-
 /**
  * A type of explicit health check that can be performed on a device, e.g network health check
  */
@@ -40,7 +38,7 @@
     boolean isPending();
 
     /**
-     * Returns the {@link PackageInfo} object this checker can make requests for.
+     * Returns the name of the package this checker can make requests for.
      */
-    PackageInfo getSupportedPackage();
+    String getSupportedPackageName();
 }
diff --git a/packages/ExtServices/src/android/ext/services/watchdog/NetworkChecker.java b/packages/ExtServices/src/android/ext/services/watchdog/NetworkChecker.java
index 09b319e..5722e09 100644
--- a/packages/ExtServices/src/android/ext/services/watchdog/NetworkChecker.java
+++ b/packages/ExtServices/src/android/ext/services/watchdog/NetworkChecker.java
@@ -21,7 +21,6 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.service.watchdog.ExplicitHealthCheckService;
-import android.service.watchdog.PackageInfo;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -35,8 +34,6 @@
     private final Object mLock = new Object();
     private final ExplicitHealthCheckService mService;
     private final String mPackageName;
-    // TODO: Receive from DeviceConfig flag
-    private final long mRequestDurationMillis = 0;
     @GuardedBy("mLock")
     private boolean mIsPending;
 
@@ -76,8 +73,8 @@
     }
 
     @Override
-    public PackageInfo getSupportedPackage() {
-        return new PackageInfo(mPackageName, mRequestDurationMillis);
+    public String getSupportedPackageName() {
+        return mPackageName;
     }
 
     // TODO(b/120598832): Also monitor NetworkCallback#onAvailable to see if we have any
diff --git a/packages/NetworkStack/res/values/config.xml b/packages/NetworkStack/res/values/config.xml
index 90f96e0..478ed6b 100644
--- a/packages/NetworkStack/res/values/config.xml
+++ b/packages/NetworkStack/res/values/config.xml
@@ -7,6 +7,9 @@
     values are meant to be the default when no other configuration is specified.
     -->
 
+    <!-- DNS probe timeout for network validation. Enough for 3 DNS queries 5 seconds apart. -->
+    <integer name="default_captive_portal_dns_probe_timeout">12500</integer>
+
     <!-- HTTP URL for network validation, to use for detecting captive portals. -->
     <string name="default_captive_portal_http_url" translatable="false">http://connectivitycheck.gstatic.com/generate_204</string>
 
@@ -27,6 +30,7 @@
 
     <!-- Configuration hooks for the above settings.
          Empty by default but may be overridden by RROs. -->
+    <integer name="config_captive_portal_dns_probe_timeout"></integer>
     <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook -->
     <string name="config_captive_portal_http_url" translatable="false"></string>
     <!--suppress CheckTagEmptyBody: overlayable resource to use as configuration hook -->
@@ -35,4 +39,8 @@
     </string-array>
     <string-array name="config_captive_portal_fallback_probe_specs" translatable="false">
     </string-array>
-</resources>
\ No newline at end of file
+
+    <!-- Customized default DNS Servers address. -->
+    <string-array name="config_default_dns_servers" translatable="false">
+    </string-array>
+</resources>
diff --git a/packages/NetworkStack/res/values/overlayable.xml b/packages/NetworkStack/res/values/overlayable.xml
index 7eeeefc..b9d5337 100644
--- a/packages/NetworkStack/res/values/overlayable.xml
+++ b/packages/NetworkStack/res/values/overlayable.xml
@@ -17,9 +17,12 @@
     <overlayable name="NetworkStackConfig">
         <policy type="product|system|vendor">
             <!-- Configuration values for NetworkMonitor -->
+            <item type="integer" name="config_captive_portal_dns_probe_timeout"/>
             <item type="string" name="config_captive_portal_http_url"/>
             <item type="string" name="config_captive_portal_https_url"/>
             <item type="array" name="config_captive_portal_fallback_urls"/>
+            <!-- Configuration value for DhcpResults -->
+            <item type="array" name="config_default_dns_servers"/>
         </policy>
     </overlayable>
 </resources>
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index af0e3bb..ca6c17a 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -45,6 +45,7 @@
 
 import android.content.Context;
 import android.net.DhcpResults;
+import android.net.InetAddresses;
 import android.net.TrafficStats;
 import android.net.ip.IpClient;
 import android.net.metrics.DhcpClientEvent;
@@ -67,6 +68,7 @@
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.TrafficStatsConstants;
 import com.android.internal.util.WakeupMessage;
+import com.android.networkstack.R;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -500,6 +502,18 @@
 
     private void acceptDhcpResults(DhcpResults results, String msg) {
         mDhcpLease = results;
+        if (mDhcpLease.dnsServers.isEmpty()) {
+            // supplement customized dns servers
+            String[] dnsServersList =
+                    mContext.getResources().getStringArray(R.array.config_default_dns_servers);
+            for (final String dnsServer : dnsServersList) {
+                try {
+                    mDhcpLease.dnsServers.add(InetAddresses.parseNumericAddress(dnsServer));
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG, "Invalid default DNS server: " + dnsServer, e);
+                }
+            }
+        }
         mOffer = null;
         Log.d(TAG, msg + " lease: " + mDhcpLease);
         notifySuccess();
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index d21b5f7..b8ab94c 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -647,4 +647,9 @@
             }
         }
     }
+
+    @Override
+    public int getInterfaceVersion() {
+        return this.VERSION;
+    }
 }
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 80d139c..96e09fa 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -557,6 +557,11 @@
             checkNetworkStackCallingPermission();
             IpClient.this.removeKeepalivePacketFilter(slot);
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 
     public String getInterfaceName() {
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index 97e8186..2934e1c 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -63,6 +63,49 @@
      */
     public static final String CAPTIVE_PORTAL_USE_HTTPS = "captive_portal_use_https";
 
+    /**
+     * The URL used for HTTPS captive portal detection upon a new connection.
+     * A 204 response code from the server is used for validation.
+     */
+    public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
+
+    /**
+     * The URL used for HTTP captive portal detection upon a new connection.
+     * A 204 response code from the server is used for validation.
+     */
+    public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
+
+    /**
+     * The URL used for fallback HTTP captive portal detection when previous HTTP
+     * and HTTPS captive portal detection attemps did not return a conclusive answer.
+     */
+    public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
+
+    /**
+     * What to do when connecting a network that presents a captive portal.
+     * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
+     *
+     * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
+     */
+    public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
+
+    /**
+     * Don't attempt to detect captive portals.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
+
+    /**
+     * When detecting a captive portal, display a notification that
+     * prompts the user to sign in.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
+
+    /**
+     * When detecting a captive portal, immediately disconnect from the
+     * network and do not reconnect to that network in the future.
+     */
+    public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
+
     static {
         System.loadLibrary("networkstackutilsjni");
     }
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index a0a90fd..a6d7484 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -251,6 +251,11 @@
                 }
             }
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 
     private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
@@ -325,5 +330,10 @@
             checkNetworkStackCallingPermission();
             mNm.notifyNetworkCapabilitiesChanged(nc);
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 }
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 093235e..bacec78 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -44,6 +44,12 @@
 import static android.net.util.DataStallUtils.DEFAULT_DATA_STALL_VALID_DNS_TIME_THRESHOLD_MS;
 import static android.net.util.DataStallUtils.DEFAULT_DNS_LOG_SIZE;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_FALLBACK_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTPS_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_HTTP_URL;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_IGNORE;
+import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_MODE_PROMPT;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT;
 import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;
@@ -59,6 +65,7 @@
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.DnsResolver;
 import android.net.INetworkMonitor;
 import android.net.INetworkMonitorCallbacks;
 import android.net.LinkProperties;
@@ -122,6 +129,7 @@
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 
 /**
@@ -136,8 +144,13 @@
                                                       + "AppleWebKit/537.36 (KHTML, like Gecko) "
                                                       + "Chrome/60.0.3112.32 Safari/537.36";
 
+    @VisibleForTesting
+    static final String CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT =
+            "captive_portal_dns_probe_timeout";
+
     private static final int SOCKET_TIMEOUT_MS = 10000;
     private static final int PROBE_TIMEOUT_MS  = 3000;
+
     enum EvaluationResult {
         VALIDATED(true),
         CAPTIVE_PORTAL(false);
@@ -1168,10 +1181,10 @@
     }
 
     private boolean getIsCaptivePortalCheckEnabled() {
-        String symbol = Settings.Global.CAPTIVE_PORTAL_MODE;
-        int defaultValue = Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT;
+        String symbol = CAPTIVE_PORTAL_MODE;
+        int defaultValue = CAPTIVE_PORTAL_MODE_PROMPT;
         int mode = mDependencies.getSetting(mContext, symbol, defaultValue);
-        return mode != Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE;
+        return mode != CAPTIVE_PORTAL_MODE_IGNORE;
     }
 
     private boolean getUseHttpsValidation() {
@@ -1181,8 +1194,34 @@
 
     private String getCaptivePortalServerHttpsUrl() {
         return getSettingFromResource(mContext, R.string.config_captive_portal_https_url,
-                R.string.default_captive_portal_https_url,
-                Settings.Global.CAPTIVE_PORTAL_HTTPS_URL);
+                R.string.default_captive_portal_https_url, CAPTIVE_PORTAL_HTTPS_URL);
+    }
+
+    private int getDnsProbeTimeout() {
+        return getIntSetting(mContext, R.integer.config_captive_portal_dns_probe_timeout,
+                CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
+                R.integer.default_captive_portal_dns_probe_timeout);
+    }
+
+    /**
+     * Gets an integer setting from resources or device config
+     *
+     * configResource is used if set, followed by device config if set, followed by defaultResource.
+     * If none of these are set then an exception is thrown.
+     *
+     * TODO: move to a common location such as a ConfigUtils class.
+     * TODO(b/130324939): test that the resources can be overlayed by an RRO package.
+     */
+    @VisibleForTesting
+    int getIntSetting(@NonNull final Context context, @StringRes int configResource,
+            @NonNull String symbol, @StringRes int defaultResource) {
+        final Resources res = context.getResources();
+        try {
+            return res.getInteger(configResource);
+        } catch (Resources.NotFoundException e) {
+            return mDependencies.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY,
+                    symbol, res.getInteger(defaultResource));
+        }
     }
 
     /**
@@ -1194,8 +1233,7 @@
      */
     public String getCaptivePortalServerHttpUrl() {
         return getSettingFromResource(mContext, R.string.config_captive_portal_http_url,
-                R.string.default_captive_portal_http_url,
-                Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+                R.string.default_captive_portal_http_url, CAPTIVE_PORTAL_HTTP_URL);
     }
 
     private int getConsecutiveDnsTimeoutThreshold() {
@@ -1224,8 +1262,8 @@
 
     private URL[] makeCaptivePortalFallbackUrls() {
         try {
-            final String firstUrl = mDependencies.getSetting(mContext,
-                    Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, null);
+            final String firstUrl = mDependencies.getSetting(mContext, CAPTIVE_PORTAL_FALLBACK_URL,
+                    null);
 
             final URL[] settingProviderUrls;
             if (!TextUtils.isEmpty(firstUrl)) {
@@ -1446,6 +1484,45 @@
         return sendHttpProbe(url, probeType, null);
     }
 
+    /** Do a DNS lookup for the given server, or throw UnknownHostException after timeoutMs */
+    @VisibleForTesting
+    protected InetAddress[] sendDnsProbeWithTimeout(String host, int timeoutMs)
+                throws UnknownHostException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        final AtomicReference<List<InetAddress>> resultRef = new AtomicReference<>();
+        final DnsResolver.Callback<List<InetAddress>> callback =
+                    new DnsResolver.Callback<List<InetAddress>>() {
+            public void onAnswer(List<InetAddress> answer, int rcode) {
+                if (rcode == 0) {
+                    resultRef.set(answer);
+                }
+                latch.countDown();
+            }
+            public void onError(@NonNull DnsResolver.DnsException e) {
+                validationLog("DNS error resolving " + host + ": " + e.getMessage());
+                latch.countDown();
+            }
+        };
+
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(
+                TrafficStatsConstants.TAG_SYSTEM_PROBE);
+        mDependencies.getDnsResolver().query(mNetwork, host, DnsResolver.FLAG_EMPTY,
+                r -> r.run() /* executor */, null /* cancellationSignal */, callback);
+        TrafficStats.setThreadStatsTag(oldTag);
+
+        try {
+            latch.await(timeoutMs, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+        }
+
+        List<InetAddress> result = resultRef.get();
+        if (result == null || result.size() == 0) {
+            throw new UnknownHostException(host);
+        }
+
+        return result.toArray(new InetAddress[0]);
+    }
+
     /** Do a DNS resolution of the given server. */
     private void sendDnsProbe(String host) {
         if (TextUtils.isEmpty(host)) {
@@ -1457,7 +1534,7 @@
         int result;
         String connectInfo;
         try {
-            InetAddress[] addresses = mNetwork.getAllByName(host);
+            InetAddress[] addresses = sendDnsProbeWithTimeout(host, getDnsProbeTimeout());
             StringBuffer buffer = new StringBuffer();
             for (InetAddress address : addresses) {
                 buffer.append(',').append(address.getHostAddress());
@@ -1782,6 +1859,10 @@
             return new OneAddressPerFamilyNetwork(network);
         }
 
+        public DnsResolver getDnsResolver() {
+            return DnsResolver.getInstance();
+        }
+
         public Random getRandom() {
             return new Random();
         }
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
index bee4bbd9..6a6bf83 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
@@ -494,4 +494,9 @@
         listener.onComplete(makeStatus(ERROR_INTERNAL_INTERRUPTED));
         return true;
     }
+
+    @Override
+    public int getInterfaceVersion() {
+        return this.VERSION;
+    }
 }
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
index 2775fde..bea7052 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
@@ -91,6 +91,11 @@
             }
 
             @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
+
+            @Override
             public IBinder asBinder() {
                 return null;
             }
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
index 7d5e9e3..f0e2f1b 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
+++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
@@ -133,6 +133,11 @@
         public void onStatusAvailable(int statusCode) {
             assertEquals(STATUS_SUCCESS, statusCode);
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     };
 
     @Before
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 594f2ca..0dc1cbf 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -33,6 +33,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -41,6 +42,7 @@
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.never;
@@ -55,6 +57,7 @@
 import android.content.Intent;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.DnsResolver;
 import android.net.INetworkMonitorCallbacks;
 import android.net.InetAddresses;
 import android.net.LinkProperties;
@@ -69,6 +72,7 @@
 import android.os.Bundle;
 import android.os.ConditionVariable;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -79,6 +83,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.networkstack.R;
 import com.android.networkstack.metrics.DataStallDetectionStats;
 import com.android.networkstack.metrics.DataStallStatsUtils;
 
@@ -96,8 +101,12 @@
 import java.net.HttpURLConnection;
 import java.net.InetAddress;
 import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Random;
+import java.util.concurrent.Executor;
 
 import javax.net.ssl.SSLHandshakeException;
 
@@ -111,6 +120,7 @@
     private @Mock IpConnectivityLog mLogger;
     private @Mock SharedLog mValidationLogger;
     private @Mock NetworkInfo mNetworkInfo;
+    private @Mock DnsResolver mDnsResolver;
     private @Mock ConnectivityManager mCm;
     private @Mock TelephonyManager mTelephony;
     private @Mock WifiManager mWifi;
@@ -156,10 +166,36 @@
     private static final NetworkCapabilities NO_INTERNET_CAPABILITIES = new NetworkCapabilities()
             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
 
+    private void setDnsAnswers(String[] answers) throws UnknownHostException {
+        if (answers == null) {
+            doThrow(new UnknownHostException()).when(mNetwork).getAllByName(any());
+            doNothing().when(mDnsResolver).query(any(), any(), anyInt(), any(), any(), any());
+            return;
+        }
+
+        List<InetAddress> answerList = new ArrayList<>();
+        for (String answer : answers) {
+            answerList.add(InetAddresses.parseNumericAddress(answer));
+        }
+        InetAddress[] answerArray = answerList.toArray(new InetAddress[0]);
+
+        doReturn(answerArray).when(mNetwork).getAllByName(any());
+
+        doAnswer((invocation) -> {
+            Executor executor = (Executor) invocation.getArgument(3);
+            DnsResolver.Callback<List<InetAddress>> callback = invocation.getArgument(5);
+            new Handler(Looper.getMainLooper()).post(() -> {
+                executor.execute(() -> callback.onAnswer(answerList, 0));
+            });
+            return null;
+        }).when(mDnsResolver).query(eq(mNetwork), any(), anyInt(), any(), any(), any());
+    }
+
     @Before
     public void setUp() throws IOException {
         MockitoAnnotations.initMocks(this);
         when(mDependencies.getPrivateDnsBypassNetwork(any())).thenReturn(mNetwork);
+        when(mDependencies.getDnsResolver()).thenReturn(mDnsResolver);
         when(mDependencies.getRandom()).thenReturn(mRandom);
         when(mDependencies.getSetting(any(), eq(Settings.Global.CAPTIVE_PORTAL_MODE), anyInt()))
                 .thenReturn(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
@@ -204,9 +240,8 @@
         }).when(mNetwork).openConnection(any());
         when(mHttpConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
         when(mHttpsConnection.getRequestProperties()).thenReturn(new ArrayMap<>());
-        doReturn(new InetAddress[] {
-                InetAddresses.parseNumericAddress("192.168.0.0")
-        }).when(mNetwork).getAllByName(any());
+
+        setDnsAnswers(new String[]{"2001:db8::1", "192.0.2.2"});
 
         when(mContext.registerReceiver(any(BroadcastReceiver.class), any())).then((invocation) -> {
             mRegisteredReceivers.add(invocation.getArgument(0));
@@ -313,6 +348,44 @@
     }
 
     @Test
+    public void testGetIntSetting() throws Exception {
+        WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+
+        // No config resource, no device config. Expect to get default resource.
+        doThrow(new Resources.NotFoundException())
+                .when(mResources).getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout));
+        doAnswer(invocation -> {
+            int defaultValue = invocation.getArgument(2);
+            return defaultValue;
+        }).when(mDependencies).getDeviceConfigPropertyInt(any(),
+                eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT),
+                anyInt());
+        when(mResources.getInteger(eq(R.integer.default_captive_portal_dns_probe_timeout)))
+                .thenReturn(42);
+        assertEquals(42, wnm.getIntSetting(mContext,
+                R.integer.config_captive_portal_dns_probe_timeout,
+                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
+                R.integer.default_captive_portal_dns_probe_timeout));
+
+        // Set device config. Expect to get device config.
+        when(mDependencies.getDeviceConfigPropertyInt(any(),
+                eq(NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT), anyInt()))
+                        .thenReturn(1234);
+        assertEquals(1234, wnm.getIntSetting(mContext,
+                R.integer.config_captive_portal_dns_probe_timeout,
+                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
+                R.integer.default_captive_portal_dns_probe_timeout));
+
+        // Set config resource. Expect to get config resource.
+        when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
+                .thenReturn(5678);
+        assertEquals(5678, wnm.getIntSetting(mContext,
+                R.integer.config_captive_portal_dns_probe_timeout,
+                NetworkMonitor.CONFIG_CAPTIVE_PORTAL_DNS_PROBE_TIMEOUT,
+                R.integer.default_captive_portal_dns_probe_timeout));
+    }
+
+    @Test
     public void testIsCaptivePortal_HttpProbeIsPortal() throws IOException {
         setSslException(mHttpsConnection);
         setPortal302(mHttpConnection);
@@ -642,6 +715,45 @@
         runPartialConnectivityNetworkTest();
     }
 
+    private void assertIpAddressArrayEquals(String[] expected, InetAddress[] actual) {
+        String[] actualStrings = new String[actual.length];
+        for (int i = 0; i < actual.length; i++) {
+            actualStrings[i] = actual[i].getHostAddress();
+        }
+        assertArrayEquals("Array of IP addresses differs", expected, actualStrings);
+    }
+
+    @Test
+    public void testSendDnsProbeWithTimeout() throws Exception {
+        WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
+        final int shortTimeoutMs = 200;
+
+        String[] expected = new String[]{"2001:db8::"};
+        setDnsAnswers(expected);
+        InetAddress[] actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+        assertIpAddressArrayEquals(expected, actual);
+
+        expected = new String[]{"2001:db8::", "192.0.2.1"};
+        setDnsAnswers(expected);
+        actual = wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+        assertIpAddressArrayEquals(expected, actual);
+
+        expected = new String[0];
+        setDnsAnswers(expected);
+        try {
+            wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+            fail("No DNS results, expected UnknownHostException");
+        } catch (UnknownHostException e) {
+        }
+
+        setDnsAnswers(null);
+        try {
+            wnm.sendDnsProbeWithTimeout("www.google.com", shortTimeoutMs);
+            fail("DNS query timed out, expected UnknownHostException");
+        } catch (UnknownHostException e) {
+        }
+    }
+
     private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
         for (int i = 0; i < count; i++) {
             wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
index a00eff7..87346e5 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -136,6 +136,11 @@
             public IBinder asBinder() {
                 return null;
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 
@@ -156,6 +161,11 @@
             public IBinder asBinder() {
                 return null;
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 
@@ -178,6 +188,11 @@
             public IBinder asBinder() {
                 return null;
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 
@@ -200,6 +215,11 @@
             public IBinder asBinder() {
                 return null;
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 
@@ -219,6 +239,11 @@
             public IBinder asBinder() {
                 return null;
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 
diff --git a/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect1_copy.xml b/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect1_copy.xml
new file mode 100644
index 0000000..28265ea
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect1_copy.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect1 in frameworks/base/core/res -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="translateX"
+        android:pathData="M -522.59998,0 c 48.89972,0 166.02656,0 301.21729,0 c 197.58128,0 420.9827,0 420.9827,0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_translatex_copy"
+        android:repeatCount="infinite" />
+    <objectAnimator
+        android:duration="2000"
+        android:propertyYName="scaleX"
+        android:pathData="M 0 0.1 L 1 0.826849212646 L 2 0.1"
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_scalex_copy"
+        android:repeatCount="infinite" />
+</set>
diff --git a/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect2_copy.xml b/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect2_copy.xml
new file mode 100644
index 0000000..24cc452
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/anim/progress_indeterminate_horizontal_rect2_copy.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect2 in frameworks/base/core/res -->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+    <objectAnimator
+        android:duration="2000"
+        android:propertyXName="translateX"
+        android:pathData="M -197.60001,0 c 14.28182,0 85.07782,0 135.54689,0 c 54.26191,0 90.42461,0 168.24331,0 c 144.72154,0 316.40982,0 316.40982,0 "
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_translatex_copy"
+        android:repeatCount="infinite" />
+    <objectAnimator
+        android:duration="2000"
+        android:propertyYName="scaleX"
+        android:pathData="M 0.0,0.1 L 1.0,0.571379510698 L 2.0,0.909950256348 L 3.0,0.1"
+        android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_scalex_copy"
+        android:repeatCount="infinite" />
+</set>
diff --git a/packages/SettingsLib/ProgressBar/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml b/packages/SettingsLib/ProgressBar/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
index 2b7535a..4bf639d 100644
--- a/packages/SettingsLib/ProgressBar/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
+++ b/packages/SettingsLib/ProgressBar/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
@@ -14,15 +14,13 @@
      limitations under the License.
 -->
 
-<!-- Variant of progress_indeterminate_horizontal_material in frameworks/base/core/res, which
-     draws the whole height of the progress bar instead having blank space above and below the
-     bar. -->
+<!-- Copy of progress_indeterminate_horizontal_material_trimmed in frameworks/base/core/res -->
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
                  android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal_trimmed" >
     <target
         android:name="rect2_grp"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect2" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect2_copy" />
     <target
         android:name="rect1_grp"
-        android:animation="@*android:anim/progress_indeterminate_horizontal_rect1" />
+        android:animation="@anim/progress_indeterminate_horizontal_rect1_copy" />
 </animated-vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_scalex_copy.xml b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_scalex_copy.xml
new file mode 100644
index 0000000..d808f4f
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_scalex_copy.xml
@@ -0,0 +1,18 @@
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect1_scalex in frameworks/base/core/res -->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0 0 L 0.3665 0 C 0.47252618112021,0.062409910275 0.61541608570164,0.5 0.68325,0.5 C 0.75475061236836,0.5 0.75725829093844,0.814510098964 1.0,1.0" />
diff --git a/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_translatex_copy.xml b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_translatex_copy.xml
new file mode 100644
index 0000000..e78d5e7
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect1_translatex_copy.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect1_translatex in frameworks/base/core/res -->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 L 0.2 0 C 0.3958333333336,0.0 0.474845090492,0.206797621729 0.5916666666664,0.417082932942 C 0.7151610251224,0.639379624869 0.81625,0.974556908664 1.0,1.0 " />
diff --git a/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_scalex_copy.xml b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_scalex_copy.xml
new file mode 100644
index 0000000..43c4124
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_scalex_copy.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect2_scalex in frameworks/base/core/res -->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0,0 C 0.06834272400867,0.01992566661414 0.19220331656133,0.15855429260523 0.33333333333333,0.34926160892842 C 0.38410433133433,0.41477913453861 0.54945792615267,0.68136029463551 0.66666666666667,0.68279962777002 C 0.752586273196,0.68179620963216 0.737253971954,0.878896194318 1,1" />
diff --git a/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_translatex_copy.xml b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_translatex_copy.xml
new file mode 100644
index 0000000..615d6d6
--- /dev/null
+++ b/packages/SettingsLib/ProgressBar/res/interpolator/progress_indeterminate_horizontal_rect2_translatex_copy.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Copy of progress_indeterminate_horizontal_rect2_translatex in frameworks/base/core/res -->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 C 0.0375,0.0 0.128764607715,0.0895380946618 0.25,0.218553507947 C 0.322410320025,0.295610602487 0.436666666667,0.417591408114 0.483333333333,0.489826169306 C 0.69,0.80972296795 0.793333333333,0.950016125212 1.0,1.0 " />
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a5b7849..cd97ce8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4350,15 +4350,20 @@
                     }
 
                     if (navBarMode != -1) {
+                        String overlayPackage = "";
                         try {
-                            overlayManager.setEnabled(NAV_BAR_MODE_3BUTTON_OVERLAY,
-                                    navBarMode == NAV_BAR_MODE_3BUTTON,
-                                    UserHandle.USER_CURRENT);
-                            overlayManager.setEnabled(NAV_BAR_MODE_2BUTTON_OVERLAY,
-                                    navBarMode == NAV_BAR_MODE_2BUTTON,
-                                    UserHandle.USER_CURRENT);
-                            overlayManager.setEnabled(NAV_BAR_MODE_GESTURAL_OVERLAY,
-                                    navBarMode == NAV_BAR_MODE_GESTURAL,
+                            switch (navBarMode) {
+                                case NAV_BAR_MODE_3BUTTON:
+                                    overlayPackage = NAV_BAR_MODE_3BUTTON_OVERLAY;
+                                    break;
+                                case NAV_BAR_MODE_2BUTTON:
+                                    overlayPackage = NAV_BAR_MODE_2BUTTON_OVERLAY;
+                                    break;
+                                case NAV_BAR_MODE_GESTURAL:
+                                    overlayPackage = NAV_BAR_MODE_GESTURAL_OVERLAY;
+                                    break;
+                            }
+                            overlayManager.setEnabledExclusiveInCategory(overlayPackage,
                                     UserHandle.USER_CURRENT);
                         } catch (RemoteException e) {
                             throw new IllegalStateException(
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 463367b..86ed9e3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -33,6 +33,21 @@
         <include
              android:id="@+id/default_clock_view"
              layout="@layout/text_clock" />
+        <TextClock
+             android:id="@+id/default_clock_view_bold"
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:layout_gravity="center_horizontal"
+             android:gravity="center_horizontal"
+             android:letterSpacing="0.03"
+             android:textColor="?attr/wallpaperTextColor"
+             android:singleLine="true"
+             style="@style/widget_big_bold"
+             android:format12Hour="@string/keyguard_widget_12_hours_format"
+             android:format24Hour="@string/keyguard_widget_24_hours_format"
+             android:elegantTextHeight="false"
+             android:visibility="gone"
+             />
     </FrameLayout>
     <include layout="@layout/keyguard_status_area"
         android:id="@+id/keyguard_status_area"
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 8bbc270..6e4416a 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -66,6 +66,13 @@
         <item name="android:fontFeatureSettings">@*android:string/config_headlineFontFeatureSettings</item>
         <item name="android:ellipsize">none</item>
     </style>
+    <style name="widget_big_bold">
+        <item name="android:textStyle">bold</item>
+        <item name="android:textSize">@dimen/widget_big_font_size</item>
+        <item name="android:paddingBottom">@dimen/bottom_text_spacing_digital</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:ellipsize">none</item>
+    </style>
 
     <style name="BouncerSecurityContainer">
         <item name="android:layout_gravity">center_horizontal|bottom</item>
diff --git a/packages/SystemUI/res/drawable/button_border_selected.xml b/packages/SystemUI/res/drawable/button_border_selected.xml
new file mode 100644
index 0000000..d9299ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable/button_border_selected.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <solid
+        android:color="@color/notification_guts_selection_bg" />
+    <stroke
+        android:width="2dp"
+        android:color="?android:attr/colorAccent"/>
+    <corners android:radius="@dimen/rect_button_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/button_border_unselected.xml b/packages/SystemUI/res/drawable/button_border_unselected.xml
new file mode 100644
index 0000000..4ea3764
--- /dev/null
+++ b/packages/SystemUI/res/drawable/button_border_unselected.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle"
+       android:color="@color/notification_guts_selection_bg">
+    <stroke
+        android:width="2dp"
+        android:color="@color/GM2_grey_300"/>
+
+    <corners android:radius="@dimen/rect_button_radius" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/button_ripple_radius.xml b/packages/SystemUI/res/drawable/button_ripple_radius.xml
new file mode 100644
index 0000000..5c2857a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/button_ripple_radius.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<ripple
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:id="@android:id/mask">
+        <shape android:shape="rectangle">
+            <solid android:color="@color/notification_guts_selection_bg" />
+            <corners android:radius="@dimen/rect_button_radius" />
+        </shape>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_notification_gentle.xml b/packages/SystemUI/res/drawable/ic_notification_gentle.xml
index 7074130..de54b10 100644
--- a/packages/SystemUI/res/drawable/ic_notification_gentle.xml
+++ b/packages/SystemUI/res/drawable/ic_notification_gentle.xml
@@ -18,18 +18,18 @@
         android:id="@+id/back">
         <shape android:shape="oval">
             <solid
-                android:color="@color/GM2_green_500" />
+                android:color="@color/notification_silence_color" />
             <size
-                android:height="36dp"
-                android:width="36dp"/>
+                android:height="24dp"
+                android:width="24dp"/>
         </shape>
     </item>
     <item
         android:id="@+id/fore"
         android:gravity="center">
         <vector
-                android:width="32dp"
-                android:height="32dp"
+                android:width="13dp"
+                android:height="13dp"
                 android:viewportWidth="24"
                 android:viewportHeight="24">
             <path
diff --git a/packages/SystemUI/res/drawable/ic_notification_interruptive.xml b/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
index 0a8b3b8..f49aa4a 100644
--- a/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
+++ b/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
@@ -19,18 +19,18 @@
         android:id="@+id/back">
         <shape android:shape="oval">
             <solid
-                android:color="@color/GM2_yellow_500" />
+                android:color="@color/notification_alert_color" />
             <size
-                android:height="36dp"
-                android:width="36dp"/>
+                android:height="24dp"
+                android:width="24dp"/>
         </shape>
     </item>
     <item
         android:id="@+id/fore"
         android:gravity="center">
         <vector
-                android:width="32dp"
-                android:height="32dp"
+                android:width="13dp"
+                android:height="13dp"
                 android:viewportWidth="24"
                 android:viewportHeight="24">
             <path
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f7c6c43..a94ae0f 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -22,7 +22,7 @@
     android:layout_height="wrap_content"
     android:clickable="true"
     android:clipChildren="false"
-    android:clipToPadding="false"
+    android:clipToPadding="true"
     android:orientation="vertical"
     android:paddingStart="@*android:dimen/notification_content_margin_start"
     android:background="@color/notification_guts_bg_color">
@@ -39,69 +39,62 @@
             android:layout_width="@dimen/notification_guts_header_height"
             android:layout_height="@dimen/notification_guts_header_height"
             android:layout_centerVertical="true"
+            android:layout_alignParentStart="true"
             android:layout_marginEnd="3dp" />
         <TextView
             android:id="@+id/pkgname"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            style="@style/TextAppearance.NotificationInfo.Primary"
+            android:layout_centerVertical="true"
+            style="@style/TextAppearance.NotificationImportanceHeader"
             android:layout_marginStart="3dp"
             android:layout_marginEnd="2dp"
-            android:singleLine="true"
-            android:layout_centerVertical="true"
-            android:layout_toEndOf="@id/pkgicon" />
+            android:layout_toEndOf="@id/pkgicon"
+            android:singleLine="true" />
         <TextView
             android:id="@+id/pkg_divider"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            style="@style/TextAppearance.NotificationInfo.Primary"
+            android:layout_centerVertical="true"
+            style="@style/TextAppearance.NotificationImportanceHeader"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
-            android:text="@*android:string/notification_header_divider_symbol"
-            android:layout_centerVertical="true"
-            android:layout_toEndOf="@id/pkgname" />
+            android:layout_toEndOf="@id/pkgname"
+            android:text="@*android:string/notification_header_divider_symbol" />
         <TextView
             android:id="@+id/delegate_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            style="@style/TextAppearance.NotificationInfo.Primary"
+            android:layout_centerVertical="true"
+            style="@style/TextAppearance.NotificationImportanceHeader"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
             android:ellipsize="end"
-            android:maxLines="1"
-            android:layout_centerVertical="true"
-            android:layout_toEndOf="@id/pkg_divider" />
-        <LinearLayout
-            android:id="@+id/info_and_settings"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_centerVertical="true"
-            android:layout_alignParentEnd="true"
-
-            android:orientation="horizontal">
-            <!-- Optional link to app. Only appears if the channel is not disabled and the app
+            android:layout_toEndOf="@id/pkg_divider"
+            android:maxLines="1" />
+        <!-- Optional link to app. Only appears if the channel is not disabled and the app
 asked for it -->
-            <ImageButton
-                android:id="@+id/app_settings"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_centerVertical="true"
-                android:visibility="gone"
-                android:background="@drawable/ripple_drawable"
-                android:contentDescription="@string/notification_app_settings"
-                android:src="@drawable/ic_info"
-                android:tint="@color/notification_guts_link_icon_tint" />
-            <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
-            <ImageButton
-                android:id="@+id/info"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_centerVertical="true"
-                android:background="@drawable/ripple_drawable"
-                android:contentDescription="@string/notification_more_settings"
-                android:src="@drawable/ic_settings"
-                android:tint="@color/notification_guts_link_icon_tint" />
-        </LinearLayout>
+        <ImageButton
+            android:id="@+id/app_settings"
+            android:layout_width="@dimen/notification_importance_toggle_size"
+            android:layout_height="@dimen/notification_importance_toggle_size"
+            android:layout_centerVertical="true"
+            android:visibility="gone"
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/notification_app_settings"
+            android:src="@drawable/ic_info"
+            android:layout_toStartOf="@id/info"
+            android:tint="@color/notification_guts_link_icon_tint"/>
+        <ImageButton
+            android:id="@+id/info"
+            android:layout_width="@dimen/notification_importance_toggle_size"
+            android:layout_height="@dimen/notification_importance_toggle_size"
+            android:layout_centerVertical="true"
+            android:background="@drawable/ripple_drawable"
+            android:contentDescription="@string/notification_more_settings"
+            android:src="@drawable/ic_settings"
+            android:layout_alignParentEnd="true"
+            android:tint="@color/notification_guts_link_icon_tint"/>
     </RelativeLayout>
 
     <!-- Channel Info Block -->
@@ -111,40 +104,22 @@
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/notification_guts_button_spacing"
         android:paddingEnd="@*android:dimen/notification_content_margin_end"
+        android:gravity="center"
         android:orientation="vertical">
-        <RelativeLayout
-            android:id="@+id/names"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-            <TextView
-                android:id="@+id/group_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                style="@style/TextAppearance.NotificationInfo.Primary"
-                android:layout_marginStart="2dp"
-                android:layout_marginEnd="2dp"
-                android:ellipsize="end"
-                android:maxLines="1"
-                android:layout_centerVertical="true" />
-            <TextView
-                android:id="@+id/pkg_group_divider"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                style="@style/TextAppearance.NotificationInfo.Primary"
-                android:layout_marginStart="2dp"
-                android:layout_marginEnd="2dp"
-                android:text="@*android:string/notification_header_divider_symbol"
-                android:layout_centerVertical="true"
-                android:layout_toEndOf="@id/group_name" />
-            <!-- Channel Name -->
-            <TextView
-                android:id="@+id/channel_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                style="@style/TextAppearance.NotificationInfo.Primary"
-                android:layout_toEndOf="@id/pkg_group_divider"/>
-        </RelativeLayout>
+        <!-- Channel Name -->
+        <TextView
+            android:id="@+id/channel_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            style="@style/TextAppearance.NotificationImportanceChannel"/>
+        <TextView
+            android:id="@+id/group_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@style/TextAppearance.NotificationImportanceChannelGroup"
+            android:ellipsize="end"
+            android:maxLines="1"/>
     </LinearLayout>
 
     <LinearLayout
@@ -212,8 +187,8 @@
         android:id="@+id/inline_controls"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/notification_guts_button_spacing"
         android:paddingEnd="@*android:dimen/notification_content_margin_end"
+        android:layout_marginTop="@dimen/notification_guts_option_vertical_padding"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:orientation="vertical">
@@ -225,7 +200,6 @@
             android:visibility="gone"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="@dimen/notification_guts_option_vertical_padding"
             style="@*android:style/TextAppearance.DeviceDefault.Notification" />
 
         <!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings-->
@@ -235,7 +209,6 @@
             android:visibility="gone"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="@dimen/notification_guts_option_vertical_padding"
             style="@*android:style/TextAppearance.DeviceDefault.Notification" />
 
         <LinearLayout
@@ -243,105 +216,68 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
-            <!-- Interruptive row -->
+
             <LinearLayout
-                android:id="@+id/alert_row"
+                android:id="@+id/buttons"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingTop="@dimen/notification_guts_option_vertical_padding"
-                android:paddingBottom="@dimen/notification_guts_option_vertical_padding"
-                android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
-                android:orientation="horizontal">
+                android:orientation="horizontal"
+                android:gravity="center">
 
-                <ImageView
-                    android:id="@+id/int_alert"
-                    android:src="@drawable/ic_notification_interruptive"
-                    android:background="@android:color/transparent"
-                    android:layout_gravity="center"
+                <Button
+                    android:id="@+id/alert"
+                    android:minWidth="@dimen/notification_importance_button_width"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:contentDescription="@string/inline_silent_button_alert"/>
+                    android:minHeight="@dimen/notification_importance_toggle_size"
+                    android:paddingStart="@dimen/notification_importance_button_horiz_padding"
+                    android:paddingEnd="@dimen/notification_importance_button_horiz_padding"
+                    android:drawablePadding="@dimen/notification_importance_drawable_padding"
+                    android:foreground="@drawable/button_ripple_radius"
+                    android:drawableLeft="@drawable/ic_notification_interruptive"
+                    android:text="@string/notification_alert_title" />
 
-                <LinearLayout
-                    android:layout_width="match_parent"
+                <Button
+                    android:id="@+id/silence"
+                    android:minWidth="@dimen/notification_importance_button_width"
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
-                    android:paddingEnd="@dimen/notification_guts_option_horizontal_padding"
-                    android:orientation="vertical">
-                    <TextView
-                        android:id="@+id/int_alert_label"
-                        android:text="@string/inline_silent_button_alert"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        android:maxLines="1"
-                        style="@style/TextAppearance.NotificationInfo.Primary"/>
-                    <TextView
-                        android:id="@+id/int_alert_summary"
-                        android:text="@string/hint_text_alert"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        style="@style/TextAppearance.NotificationInfo.Secondary"/>
-                </LinearLayout>
+                    android:minHeight="@dimen/notification_importance_toggle_size"
+                    android:paddingStart="@dimen/notification_importance_button_horiz_padding"
+                    android:paddingEnd="@dimen/notification_importance_button_horiz_padding"
+                    android:drawablePadding="@dimen/notification_importance_drawable_padding"
+                    android:foreground="@drawable/button_ripple_radius"
+                    android:layout_marginStart="@dimen/notification_importance_button_separation"
+                    android:drawableLeft="@drawable/ic_notification_gentle"
+                    android:text="@string/notification_silence_title" />
             </LinearLayout>
 
-            <!-- Gentle row -->
-            <LinearLayout
-                android:id="@+id/silent_row"
+            <TextView
+                android:id="@+id/description"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:paddingTop="@dimen/notification_guts_option_vertical_padding"
-                android:paddingBottom="@dimen/notification_guts_option_vertical_padding"
-                android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
-                android:layout_marginTop="@dimen/notification_guts_option_vertical_margin"
-                android:orientation="horizontal">
-                <ImageView
-                    android:id="@+id/int_silent"
-                    android:src="@drawable/ic_notification_gentle"
-                    android:layout_gravity="center"
-                    android:layout_width="36dp"
-                    android:layout_height="36dp"
-                    android:background="@android:color/transparent"
-                    android:contentDescription="@string/inline_silent_button_silent"/>
-                <LinearLayout
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:orientation="vertical"
-                    android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
-                    android:paddingEnd="@dimen/notification_guts_option_horizontal_padding">
-                    <TextView
-                        android:id="@+id/int_silent_label"
-                        android:text="@string/inline_silent_button_silent"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        android:maxLines="1"
-                        style="@style/TextAppearance.NotificationInfo.Primary"/>
-                    <TextView
-                        android:id="@+id/int_silent_summary"
-                        android:text="@string/hint_text_silent"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        style="@style/TextAppearance.NotificationInfo.Secondary"/>
-                </LinearLayout>
-            </LinearLayout>
+                android:text="@string/notification_alert_title"
+                android:gravity="center"
+                android:layout_marginTop="@dimen/notification_importance_text_marginTop"
+                android:paddingStart="@dimen/notification_importance_description_padding"
+                android:paddingEnd="@dimen/notification_importance_description_padding"
+                android:textAppearance="@style/TextAppearance.NotificationImportanceDetail" />
         </LinearLayout>
 
         <RelativeLayout
             android:id="@+id/bottom_buttons"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="@dimen/notification_guts_button_spacing"
-            android:paddingBottom="@dimen/notification_guts_button_spacing">
+            android:paddingTop="@dimen/notification_guts_button_spacing" >
             <TextView
                 android:id="@+id/turn_off_notifications"
                 android:text="@string/inline_turn_off_notifications"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
                 android:layout_alignParentStart="true"
+                android:layout_centerVertical="true"
+                android:minWidth="@dimen/notification_importance_toggle_size"
+                android:minHeight="@dimen/notification_importance_toggle_size"
                 android:maxWidth="200dp"
                 style="@style/TextAppearance.NotificationInfo.Button"/>
             <TextView
@@ -351,6 +287,8 @@
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
                 android:maxWidth="125dp"
+                android:minWidth="@dimen/notification_importance_toggle_size"
+                android:minHeight="@dimen/notification_importance_toggle_size"
                 android:layout_alignParentEnd="true"
                 style="@style/TextAppearance.NotificationInfo.Button"/>
         </RelativeLayout>
@@ -376,6 +314,8 @@
             android:id="@+id/undo"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:minWidth="@dimen/notification_importance_toggle_size"
+            android:minHeight="@dimen/notification_importance_toggle_size"
             android:layout_marginTop="@dimen/notification_guts_button_spacing"
             android:layout_marginBottom="@dimen/notification_guts_button_spacing"
             android:layout_marginStart="@dimen/notification_guts_button_side_margin"
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 37c6d9f..5a33f82 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -22,17 +22,6 @@
     android:paddingStart="@dimen/status_bar_padding_start"
     android:paddingEnd="@dimen/status_bar_padding_end">
 
-    <TextView
-        android:id="@+id/long_press_tooltip"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="start|center_vertical"
-        android:alpha="0"
-        android:text="@string/quick_settings_header_onboarding_text"
-        android:textAppearance="@style/TextAppearance.QS.TileLabel"
-        android:textColor="?android:attr/textColorSecondary"
-        android:visibility="invisible" />
-
     <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
@@ -45,8 +34,7 @@
             android:layout_height="match_parent"
             android:layout_gravity="start|center_vertical"
             android:layout_weight="1"
-            android:gravity="center_vertical"
-            android:alpha="0" >
+            android:gravity="center_vertical" >
 
             <LinearLayout
                 android:id = "@+id/alarm_container"
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 8a0aaea..f9bf47b 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -45,6 +45,8 @@
     <color name="notification_guts_selection_bg">#202124</color>
     <color name="notification_guts_selection_border">#669DF6</color>
     <color name="notification_guts_link_icon_tint">@color/GM2_grey_200</color>
+    <color name="notification_guts_sub_text_color">@color/GM2_grey_200</color>
+    <color name="notification_guts_header_text_color">@color/GM2_grey_100</color>
 
     <!-- The color of the background in the top part of QSCustomizer -->
     <color name="qs_customize_background">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index b2a5075..d2a005f 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -90,7 +90,11 @@
 
     <color name="notification_guts_selection_bg">#FFFFFF</color>
     <color name="notification_guts_selection_border">#4285F4</color>
-    <color name="notification_guts_link_icon_tint">@color/GM2_grey_900</color>
+    <color name="notification_guts_link_icon_tint">@color/GM2_grey_700</color>
+    <color name="notification_guts_sub_text_color">@color/GM2_grey_700</color>
+    <color name="notification_guts_header_text_color">@color/GM2_grey_900</color>
+    <color name="notification_silence_color">#FF32c1de</color>
+    <color name="notification_alert_color">#FFF87B2B</color>
 
     <color name="assist_orb_color">#ffffff</color>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7d76160..5e84549 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -206,11 +206,26 @@
     <dimen name="notification_guts_option_horizontal_padding">15dp</dimen>
 
     <!-- The vertical space between items in the alert selections in the inline settings -->
-    <dimen name="notification_guts_option_vertical_padding">15dp</dimen>
+    <dimen name="notification_guts_option_vertical_padding">24dp</dimen>
 
     <!-- The vertical space between the alert selections in the inline settings -->
     <dimen name="notification_guts_option_vertical_margin">6dp</dimen>
 
+    <dimen name="notification_importance_toggle_size">48dp</dimen>
+    <dimen name="notification_importance_toggle_marginTop">28dp</dimen>
+    <dimen name="notification_importance_toggle_marginBottom">28dp</dimen>
+    <dimen name="notification_importance_text_marginTop">20dp</dimen>
+    <dimen name="notification_importance_button_separation">16dp</dimen>
+    <dimen name="notification_importance_button_width">178dp</dimen>
+    <dimen name="notification_importance_button_horiz_padding">28dp</dimen>
+    <dimen name="notification_importance_drawable_padding">8dp</dimen>
+    <dimen name="notification_importance_description_padding">20dp</dimen>
+    <dimen name="notification_importance_description_text">12sp</dimen>
+    <dimen name="notification_importance_channel_text">16sp</dimen>
+    <dimen name="notification_importance_channel_group_text">14sp</dimen>
+    <dimen name="notification_importance_button_text">16sp</dimen>
+    <dimen name="rect_button_radius">8dp</dimen>
+
     <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
     <dimen name="snooze_snackbar_min_height">56dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0b0822c..a2039d0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -659,6 +659,9 @@
     <!-- Accessibility text describing the presence of active location requests by one or more apps -->
     <string name="accessibility_location_active">Location requests active</string>
 
+    <!-- Accessibility text describing sensors off active. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_sensors_off_active">Sensors off active</string>
+
     <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_clear_all">Clear all notifications.</string>
 
@@ -1648,17 +1651,29 @@
     <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
     <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
 
-    <!-- Hint text for block button in the interruptiveness settings [CHAR_LIMIT=NONE]-->
-    <string name="hint_text_block">Blocked notifications do not appear anywhere or play a sound. You can unblock notifications in settings.</string>
+    <!-- [CHAR LIMIT=100] Notification Importance title -->
+    <string name="notification_silence_title">Gentle</string>
 
-    <!-- Hint text for silent button in the interruptiveness settings [CHAR_LIMIT=NONE]-->
-    <string name="hint_text_silent">Silent notifications appear in the shade, but do not appear on the lock screen, present a banner, or play a sound.</string>
+    <!-- [CHAR LIMIT=100] Notification Importance title -->
+    <string name="notification_alert_title">Prioritized</string>
 
-    <!-- Hint text for alert button in the interruptiveness settings [CHAR_LIMIT=NONE]-->
-    <string name="hint_text_alert">These notifications will make a sound and show in the notification drawer, status bar, and lock screen</string>
+    <!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
+    <string name="notification_channel_summary_low">Always silent. Displays in pull-down shade.</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
+    <string name="notification_channel_summary_low_status">Always silent. Displays in pull-down shade &amp; status bar.</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
+    <string name="notification_channel_summary_low_lock">Always silent. Displays in pull-down shade &amp; on lock screen.</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
+    <string name="notification_channel_summary_low_status_lock">Always silent. Displays in pull-down shade, status bar &amp; on lock screen.</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: normal importance level summary -->
+    <string name="notification_channel_summary_default">Makes sound and displays in pull-down shade, status bar &amp; on lock screen.</string>
 
     <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
-    <string name="notification_unblockable_desc">These notifications can\'t be turned off</string>
+    <string name="notification_unblockable_desc">These notifications can\'t be modified.</string>
 
     <!-- Notification: Control panel: label that displays when viewing settings for a group of notifications posted to multiple channels. -->
     <string name="notification_multichannel_desc">This group of notifications cannot be configured here</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index eb68b0f..9b471c9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -426,57 +426,71 @@
     <style name="TunerPreferenceTheme" parent="@style/PreferenceThemeOverlay.SettingsBase">
     </style>
 
-    <style name="TextAppearance.NotificationInfo">
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
-        <item name="android:textColor">@color/notification_primary_text_color</item>
-    </style>
-
-    <style name="TextAppearance.NotificationInfo.Primary">
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
-        <item name="android:textSize">16sp</item>
-        <item name="android:alpha">0.87</item>
-    </style>
-
     <style name="TextAppearance.NotificationInfo.Confirmation">
         <item name="android:textSize">14sp</item>
         <item name="android:alpha">0.87</item>
     </style>
 
+    <style name="TextAppearance.NotificationInfo">
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textColor">@color/notification_primary_text_color</item>
+    </style>
+
     <style name="TextAppearance.NotificationInfo.Secondary">
         <item name="android:textSize">14sp</item>
         <item name="android:alpha">0.54</item>
     </style>
 
-    <style name="TextAppearance.NotificationInfo.ButtonLabel">
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
-        <item name="android:textSize">14sp</item>
-        <item name="android:alpha">0.54</item>
-        <item name="android:paddingTop">4dp</item>
-        <item name="android:paddingBottom">16dp</item>
-    </style>
-
-    <style name="TextAppearance.NotificationInfo.HintText">
-        <item name="android:textSize">12sp</item>
-        <item name="android:alpha">0.54</item>
-    </style>
-
-    <style name="TextAppearance.NotificationInfo.Secondary.Warning">
-        <item name="android:textColor">?android:attr/colorError</item>
-    </style>
-
-    <style name="TextAppearance.NotificationInfo.Secondary.Link">
-        <item name="android:textColor">?android:attr/colorAccent</item>
-    </style>
-
     <style name="TextAppearance.NotificationInfo.Button">
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
         <item name="android:textSize">16sp</item>
         <item name="android:textColor">?android:attr/colorAccent</item>
         <item name="android:background">@drawable/btn_borderless_rect</item>
-        <item name="android:gravity">center</item>
+        <item name="android:gravity">center_vertical</item>
         <item name="android:focusable">true</item>
     </style>
 
+    <style name="TextAppearance.NotificationImportanceChannel">
+        <item name="android:textSize">@dimen/notification_importance_channel_text</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
+        <item name="android:textColor">@color/notification_guts_header_text_color</item>
+        <item name="android:textSize">@dimen/notification_importance_channel_text</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceChannelGroup">
+        <item name="android:textSize">@dimen/notification_importance_channel_group_text</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textColor">@color/notification_guts_sub_text_color</item>
+        <item name="android:textSize">@dimen/notification_importance_channel_group_text</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceHeader">
+        <item name="android:textSize">@dimen/notification_importance_description_text</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textColor">@color/notification_guts_header_text_color</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceDetail">
+        <item name="android:textSize">@dimen/notification_importance_description_text</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textColor">@color/notification_guts_sub_text_color</item>
+        <item name="android:gravity">center</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceButton">
+        <item name="android:textSize">@dimen/notification_importance_button_text</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
+        <item name="android:gravity">center</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceButton.Selected" parent="TextAppearance.NotificationImportanceButton">
+        <item name="android:textColor">?android:attr/colorAccent</item>
+    </style>
+
+    <style name="TextAppearance.NotificationImportanceButton.Unselected" parent="TextAppearance.NotificationImportanceButton">
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+    </style>
+
     <style name="TextAppearance.HeadsUpStatusBarText"
            parent="@*android:style/TextAppearance.DeviceDefault.Notification.Info">
     </style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index 39da194..9dd5bb4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -19,6 +19,9 @@
 import android.graphics.HardwareRenderer;
 import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
 import android.view.Surface;
 import android.view.View;
 import android.view.ViewRootImpl;
@@ -33,8 +36,15 @@
  */
 public class SyncRtSurfaceTransactionApplierCompat {
 
+    private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
+
     private final Surface mTargetSurface;
     private final ViewRootImpl mTargetViewRootImpl;
+    private final Handler mApplyHandler;
+
+    private int mSequenceNumber = 0;
+    private int mPendingSequenceNumber = 0;
+    private Runnable mAfterApplyCallback;
 
     /**
      * @param targetView The view in the surface that acts as synchronization anchor.
@@ -42,6 +52,26 @@
     public SyncRtSurfaceTransactionApplierCompat(View targetView) {
         mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
         mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
+
+        mApplyHandler = new Handler(new Callback() {
+            @Override
+            public boolean handleMessage(Message msg) {
+                if (msg.what == MSG_UPDATE_SEQUENCE_NUMBER) {
+                    onApplyMessage(msg.arg1);
+                    return true;
+                }
+                return false;
+            }
+        });
+    }
+
+    private void onApplyMessage(int seqNo) {
+        mSequenceNumber = seqNo;
+        if (mSequenceNumber == mPendingSequenceNumber && mAfterApplyCallback != null) {
+            Runnable r = mAfterApplyCallback;
+            mAfterApplyCallback = null;
+            r.run();
+        }
     }
 
     /**
@@ -54,10 +84,15 @@
         if (mTargetViewRootImpl == null || mTargetViewRootImpl.getView() == null) {
             return;
         }
+
+        mPendingSequenceNumber++;
+        final int toApplySeqNo = mPendingSequenceNumber;
         mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() {
             @Override
             public void onFrameDraw(long frame) {
                 if (mTargetSurface == null || !mTargetSurface.isValid()) {
+                    Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
+                            .sendToTarget();
                     return;
                 }
                 TransactionCompat t = new TransactionCompat();
@@ -70,6 +105,7 @@
                 }
                 t.setEarlyWakeup();
                 t.apply();
+                mApplyHandler.sendEmptyMessage(toApplySeqNo);
             }
         });
 
@@ -77,6 +113,28 @@
         mTargetViewRootImpl.getView().invalidate();
     }
 
+    /**
+     * Calls the runnable when any pending apply calls have completed
+     */
+    public void addAfterApplyCallback(final Runnable afterApplyCallback) {
+        if (mSequenceNumber == mPendingSequenceNumber) {
+            afterApplyCallback.run();
+        } else {
+            if (mAfterApplyCallback == null) {
+                mAfterApplyCallback = afterApplyCallback;
+            } else {
+                final Runnable oldCallback = mAfterApplyCallback;
+                mAfterApplyCallback = new Runnable() {
+                    @Override
+                    public void run() {
+                        afterApplyCallback.run();
+                        oldCallback.run();
+                    }
+                };
+            }
+        }
+    }
+
     public static void applyParams(TransactionCompat t,
             SyncRtSurfaceTransactionApplierCompat.SurfaceParams params) {
         t.setMatrix(params.surface, params.matrix);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index fbb30d2..20de4d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -3,7 +3,6 @@
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.app.WallpaperManager;
@@ -12,6 +11,7 @@
 import android.graphics.Paint.Style;
 import android.transition.ChangeBounds;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.transition.TransitionValues;
 import android.util.AttributeSet;
@@ -68,6 +68,11 @@
     private final Transition mTransition;
 
     /**
+     * Listener for layout transitions.
+     */
+    private final Transition.TransitionListener mTransitionListener;
+
+    /**
      * Optional/alternative clock injected via plugin.
      */
     private ClockPlugin mClockPlugin;
@@ -78,6 +83,12 @@
     private TextClock mClockView;
 
     /**
+     * Default clock, bold version.
+     * Used to transition to bold when shrinking the default clock.
+     */
+    private TextClock mClockViewBold;
+
+    /**
      * Frame for default and custom clock.
      */
     private FrameLayout mSmallClockFrame;
@@ -142,6 +153,7 @@
         mSysuiColorExtractor = colorExtractor;
         mClockManager = clockManager;
         mTransition = new ClockBoundsTransition();
+        mTransitionListener = new ClockBoundsTransitionListener();
     }
 
     /**
@@ -155,6 +167,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mClockView = findViewById(R.id.default_clock_view);
+        mClockViewBold = findViewById(R.id.default_clock_view_bold);
         mSmallClockFrame = findViewById(R.id.clock_view);
         mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
     }
@@ -165,6 +178,7 @@
         mClockManager.addOnClockChangedListener(mClockChangedListener);
         mStatusBarStateController.addCallback(mStateListener);
         mSysuiColorExtractor.addOnColorsChangedListener(mColorsListener);
+        mTransition.addListener(mTransitionListener);
         updateColors();
     }
 
@@ -174,6 +188,7 @@
         mClockManager.removeOnClockChangedListener(mClockChangedListener);
         mStatusBarStateController.removeCallback(mStateListener);
         mSysuiColorExtractor.removeOnColorsChangedListener(mColorsListener);
+        mTransition.removeListener(mTransitionListener);
         setClockPlugin(null);
     }
 
@@ -193,6 +208,7 @@
         }
         if (plugin == null) {
             mClockView.setVisibility(View.VISIBLE);
+            mClockViewBold.setVisibility(View.INVISIBLE);
             mKeyguardStatusArea.setVisibility(View.VISIBLE);
             return;
         }
@@ -203,6 +219,7 @@
                     new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                             ViewGroup.LayoutParams.WRAP_CONTENT));
             mClockView.setVisibility(View.GONE);
+            mClockViewBold.setVisibility(View.GONE);
         }
         View bigClockView = plugin.getBigClockView();
         if (bigClockView != null && mBigClockContainer != null) {
@@ -242,6 +259,7 @@
      */
     public void setStyle(Style style) {
         mClockView.getPaint().setStyle(style);
+        mClockViewBold.getPaint().setStyle(style);
         if (mClockPlugin != null) {
             mClockPlugin.setStyle(style);
         }
@@ -252,6 +270,7 @@
      */
     public void setTextColor(int color) {
         mClockView.setTextColor(color);
+        mClockViewBold.setTextColor(color);
         if (mClockPlugin != null) {
             mClockPlugin.setTextColor(color);
         }
@@ -259,18 +278,22 @@
 
     public void setShowCurrentUserTime(boolean showCurrentUserTime) {
         mClockView.setShowCurrentUserTime(showCurrentUserTime);
+        mClockViewBold.setShowCurrentUserTime(showCurrentUserTime);
     }
 
     public void setTextSize(int unit, float size) {
         mClockView.setTextSize(unit, size);
+        mClockViewBold.setTextSize(unit, size);
     }
 
     public void setFormat12Hour(CharSequence format) {
         mClockView.setFormat12Hour(format);
+        mClockViewBold.setFormat12Hour(format);
     }
 
     public void setFormat24Hour(CharSequence format) {
         mClockView.setFormat24Hour(format);
+        mClockViewBold.setFormat24Hour(format);
     }
 
     /**
@@ -316,6 +339,7 @@
      */
     public void refresh() {
         mClockView.refresh();
+        mClockViewBold.refresh();
         if (mClockPlugin != null) {
             mClockPlugin.onTimeTick();
         }
@@ -356,8 +380,7 @@
 
     /**
      * Sets if the keyguard slice is showing a center-aligned header. We need a smaller clock in
-     * these
-     * cases.
+     * these cases.
      */
     public void setKeyguardShowingHeader(boolean hasHeader) {
         if (mShowingHeader == hasHeader || hasCustomClock()) {
@@ -371,8 +394,11 @@
         int paddingBottom = mContext.getResources().getDimensionPixelSize(mShowingHeader
                 ? R.dimen.widget_vertical_padding_clock : R.dimen.header_subtitle_padding);
         mClockView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
+        mClockViewBold.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize);
         mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(),
                 mClockView.getPaddingRight(), paddingBottom);
+        mClockViewBold.setPadding(mClockViewBold.getPaddingLeft(), mClockViewBold.getPaddingTop(),
+                mClockViewBold.getPaddingRight(), paddingBottom);
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
@@ -389,6 +415,7 @@
         pw.println("KeyguardClockSwitch:");
         pw.println("  mClockPlugin: " + mClockPlugin);
         pw.println("  mClockView: " + mClockView);
+        pw.println("  mClockViewBold: " + mClockViewBold);
         pw.println("  mSmallClockFrame: " + mSmallClockFrame);
         pw.println("  mBigClockContainer: " + mBigClockContainer);
         pw.println("  mKeyguardStatusArea: " + mKeyguardStatusArea);
@@ -400,11 +427,15 @@
 
     /**
      * Special layout transition that scales the clock view as its bounds change, to make it look
-     * like
-     * the text is shrinking.
+     * like the text is shrinking.
      */
     private class ClockBoundsTransition extends ChangeBounds {
 
+        /**
+         * Animation fraction when text is transitioned to/from bold.
+         */
+        private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
+
         ClockBoundsTransition() {
             setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2);
             setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
@@ -435,29 +466,51 @@
                         .getDimensionPixelSize(R.dimen.widget_small_font_size);
                 float startScale = mShowingHeader
                         ? bigFontSize / smallFontSize : smallFontSize / bigFontSize;
+                final int normalViewVisibility = mShowingHeader ? View.INVISIBLE : View.VISIBLE;
+                final int boldViewVisibility = mShowingHeader ? View.VISIBLE : View.INVISIBLE;
+                final float boldTransitionFraction = mShowingHeader ? TO_BOLD_TRANSITION_FRACTION :
+                        1f - TO_BOLD_TRANSITION_FRACTION;
                 boundsAnimator.addUpdateListener(animation -> {
+                    final float fraction = animation.getAnimatedFraction();
+                    if (fraction > boldTransitionFraction) {
+                        mClockView.setVisibility(normalViewVisibility);
+                        mClockViewBold.setVisibility(boldViewVisibility);
+                    }
                     float scale = MathUtils.lerp(startScale, 1f /* stop */,
                             animation.getAnimatedFraction());
                     mClockView.setPivotX(mClockView.getWidth() / 2f);
+                    mClockViewBold.setPivotX(mClockViewBold.getWidth() / 2f);
                     mClockView.setPivotY(0);
+                    mClockViewBold.setPivotY(0);
                     mClockView.setScaleX(scale);
+                    mClockViewBold.setScaleX(scale);
                     mClockView.setScaleY(scale);
-                });
-                boundsAnimator.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animator) {
-                        mClockView.setScaleX(1f);
-                        mClockView.setScaleY(1f);
-                    }
-
-                    @Override
-                    public void onAnimationCancel(Animator animator) {
-                        onAnimationEnd(animator);
-                    }
+                    mClockViewBold.setScaleY(scale);
                 });
             }
 
             return animator;
         }
     }
+
+    /**
+     * Transition listener for layout transition that scales the clock view.
+     */
+    private class ClockBoundsTransitionListener extends TransitionListenerAdapter {
+
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            mClockView.setVisibility(mShowingHeader ? View.INVISIBLE : View.VISIBLE);
+            mClockViewBold.setVisibility(mShowingHeader ? View.VISIBLE : View.INVISIBLE);
+            mClockView.setScaleX(1f);
+            mClockViewBold.setScaleX(1f);
+            mClockView.setScaleY(1f);
+            mClockViewBold.setScaleY(1f);
+        }
+
+        @Override
+        public void onTransitionCancel(Transition transition) {
+            onTransitionEnd(transition);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 744f88d..ef383ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -32,7 +32,6 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
 import android.app.IActivityTaskManager;
-import android.app.INotificationManager;
 import android.app.Notification;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -52,6 +51,7 @@
 import androidx.annotation.MainThread;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -131,8 +131,7 @@
     private StatusBarStateListener mStatusBarStateListener;
 
     private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-
-    private INotificationManager mNotificationManagerService;
+    private IStatusBarService mBarService;
 
     // Used for determining view rect for touch interaction
     private Rect mTempRect = new Rect();
@@ -207,13 +206,6 @@
         mNotificationEntryManager = Dependency.get(NotificationEntryManager.class);
         mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
 
-        try {
-            mNotificationManagerService = INotificationManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE));
-        } catch (ServiceManager.ServiceNotFoundException e) {
-            e.printStackTrace();
-        }
-
         mStatusBarWindowController = statusBarWindowController;
         mStatusBarStateListener = new StatusBarStateListener();
         Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
@@ -231,6 +223,9 @@
         mBubbleData = data;
         mBubbleData.setListener(mBubbleDataListener);
         mSurfaceSynchronizer = synchronizer;
+
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
     }
 
     /**
@@ -462,6 +457,18 @@
             if (mStackView != null) {
                 mStackView.removeBubble(bubble);
             }
+            if (!bubble.entry.showInShadeWhenBubble()) {
+                // The notification is gone & bubble is gone, time to actually remove it
+                mNotificationEntryManager.performRemoveNotification(bubble.entry.notification);
+            } else {
+                // The notification is still in the shade but we've removed the bubble so
+                // lets make sure NoMan knows it's not a bubble anymore
+                try {
+                    mBarService.onNotificationBubbleChanged(bubble.getKey(), false /* isBubble */);
+                } catch (RemoteException e) {
+                    // Bad things have happened
+                }
+            }
         }
 
         public void onBubbleUpdated(Bubble bubble) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 0fe6611..a381e7b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -247,6 +247,10 @@
                 }
                 if (state == DozeMachine.State.DOZE) {
                     mMachine.requestState(DozeMachine.State.DOZE_AOD);
+                    // Logs AOD open due to sensor wake up.
+                    mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                            .setType(MetricsEvent.TYPE_OPEN)
+                            .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
                 }
             }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
         } else {
@@ -254,6 +258,10 @@
             boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
             if (!pausing && !paused) {
                 mMachine.requestState(DozeMachine.State.DOZE);
+                // Logs AOD close due to sensor wake up.
+                mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING)
+                        .setType(MetricsEvent.TYPE_CLOSE)
+                        .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 505957a..e128531 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1588,6 +1588,7 @@
                 mBackgroundDrawable = mContext.getDrawable(
                         com.android.systemui.R.drawable.global_action_panel_scrim);
                 mScrimAlpha = 1f;
+                initializePanel();
             }
             mGlobalActionsLayout.setSnapToEdge(true);
             getWindow().setBackgroundDrawable(mBackgroundDrawable);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index 60dceef..84f7e89 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -170,6 +170,11 @@
         // We should not be here.
     }
 
+    @Override
+    public void notifyOutsideTouch() {
+        // Do nothing.
+    }
+
     public static AccessibilityNodeInfo obtainRootAccessibilityNodeInfo() {
         AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
         info.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
index f19445c..a1a7566 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
@@ -132,15 +132,18 @@
         }
 
         @Override
+        protected void onFinishInflate() {
+            setSelected(true);
+        }
+
+        @Override
         protected void onVisibilityChanged(View changedView, int visibility) {
             super.onVisibilityChanged(changedView, visibility);
             // Only show marquee when visible
             if (visibility == VISIBLE) {
                 setEllipsize(TextUtils.TruncateAt.MARQUEE);
-                setSelected(true);
             } else {
                 setEllipsize(TextUtils.TruncateAt.END);
-                setSelected(false);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 995dc66..4b55137 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -181,6 +181,7 @@
     private static class HeaderTileLayout extends TileLayout {
 
         private boolean mListening;
+        private Rect mClippingBounds = new Rect();
 
         public HeaderTileLayout(Context context) {
             super(context);
@@ -219,8 +220,8 @@
         @Override
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             // We only care about clipping on the right side
-            Rect bounds = new Rect(0, 0, r - l, 10000);
-            setClipBounds(bounds);
+            mClippingBounds.set(0, 0, r - l, 10000);
+            setClipBounds(mClippingBounds);
 
             calculateColumns();
 
@@ -252,9 +253,9 @@
             }
 
             final int availableWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
-            final int leftoverWithespace = availableWidth - maxTiles * mCellWidth;
+            final int leftoverWhitespace = availableWidth - maxTiles * mCellWidth;
             final int smallestHorizontalMarginNeeded;
-            smallestHorizontalMarginNeeded = leftoverWithespace / Math.max(1, maxTiles - 1);
+            smallestHorizontalMarginNeeded = leftoverWhitespace / Math.max(1, maxTiles - 1);
 
             if (smallestHorizontalMarginNeeded > 0){
                 mCellMarginHorizontal = smallestHorizontalMarginNeeded;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 2e3065a..346ffa2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -18,8 +18,6 @@
 
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.annotation.ColorInt;
 import android.app.ActivityManager;
 import android.app.AlarmManager;
@@ -39,7 +37,6 @@
 import android.service.notification.ZenModeConfig;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.Pair;
 import android.util.StatsLog;
 import android.view.DisplayCutout;
@@ -56,7 +53,6 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
-import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.DarkIconDispatcher;
@@ -123,10 +119,6 @@
     private View mSystemIconsView;
     private View mQuickQsStatusIcons;
     private View mHeaderTextContainerView;
-    /** View containing the next alarm and ringer mode info. */
-    private View mStatusContainer;
-    /** Tooltip for educating users that they can long press on icons to see more details. */
-    private View mLongPressTooltipView;
 
     private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
     private AlarmManager.AlarmClockInfo mNextAlarm;
@@ -146,8 +138,6 @@
     private BatteryMeterView mBatteryRemainingIcon;
 
     private PrivacyItemController mPrivacyItemController;
-    /** Counts how many times the long press tooltip has been shown to the user. */
-    private int mShownCount;
 
     private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
         @Override
@@ -159,11 +149,6 @@
     private boolean mHasTopCutout = false;
     private boolean mPrivacyChipLogged = false;
 
-    /**
-     * Runnable for automatically fading out the long press tooltip (as if it were animating away).
-     */
-    private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
-
     private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
         @Override
         public void privacyChanged(List<PrivacyItem> privacyItems) {
@@ -183,7 +168,6 @@
         mStatusBarIconController = statusBarIconController;
         mActivityStarter = activityStarter;
         mPrivacyItemController = privacyItemController;
-        mShownCount = getStoredShownCount();
     }
 
     @Override
@@ -199,10 +183,8 @@
         iconContainer.setShouldRestrictIcons(false);
         mIconManager = new TintedIconManager(iconContainer);
 
-        // Views corresponding to the header info section (e.g. tooltip and next alarm).
+        // Views corresponding to the header info section (e.g. ringer and next alarm).
         mHeaderTextContainerView = findViewById(R.id.header_text_container);
-        mLongPressTooltipView = findViewById(R.id.long_press_tooltip);
-        mStatusContainer = findViewById(R.id.status_container);
         mStatusSeparator = findViewById(R.id.status_separator);
         mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
         mNextAlarmTextView = findViewById(R.id.next_alarm_text);
@@ -267,7 +249,6 @@
             boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
             mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
                     : View.GONE);
-            updateTooltipShow();
         }
     }
 
@@ -351,8 +332,6 @@
         mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
     }
 
-
-
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         super.onRtlPropertiesChanged(layoutDirection);
@@ -457,21 +436,6 @@
             mPrivacyChip.setExpanded(expansionFraction > 0.5);
             mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
         }
-
-        // Check the original expansion fraction - we don't want to show the tooltip until the
-        // panel is pulled all the way out.
-        if (expansionFraction == 1f) {
-            // QS is fully expanded, bring in the tooltip.
-            showLongPressTooltip();
-        }
-    }
-
-    /** Returns the latest stored tooltip shown count from SharedPreferences. */
-    private int getStoredShownCount() {
-        return Prefs.getInt(
-                mContext,
-                Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
-                TOOLTIP_NOT_YET_SHOWN_COUNT);
     }
 
     public void disable(int state1, int state2, boolean animate) {
@@ -592,109 +556,6 @@
         updateStatusText();
     }
 
-    private void updateTooltipShow() {
-        if (hasStatusText()) {
-            hideLongPressTooltip(true /* shouldShowStatusText */);
-        } else {
-            hideStatusText();
-        }
-        updateHeaderTextContainerAlphaAnimator();
-    }
-
-    private boolean hasStatusText() {
-        return mNextAlarmTextView.getVisibility() == View.VISIBLE
-                || mRingerModeTextView.getVisibility() == View.VISIBLE;
-    }
-
-    /**
-     * Animates in the long press tooltip (as long as the next alarm text isn't currently occupying
-     * the space).
-     */
-    public void showLongPressTooltip() {
-        // If we have status text to show, don't bother fading in the tooltip.
-        if (hasStatusText()) {
-            return;
-        }
-
-        if (mShownCount < MAX_TOOLTIP_SHOWN_COUNT) {
-            mLongPressTooltipView.animate().cancel();
-            mLongPressTooltipView.setVisibility(View.VISIBLE);
-            mLongPressTooltipView.animate()
-                    .alpha(1f)
-                    .setDuration(FADE_ANIMATION_DURATION_MS)
-                    .setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            mHandler.postDelayed(
-                                    mAutoFadeOutTooltipRunnable, AUTO_FADE_OUT_DELAY_MS);
-                        }
-                    })
-                    .start();
-
-            // Increment and drop the shown count in prefs for the next time we're deciding to
-            // fade in the tooltip. We first sanity check that the tooltip count hasn't changed yet
-            // in prefs (say, from a long press).
-            if (getStoredShownCount() <= mShownCount) {
-                Prefs.putInt(mContext, Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, ++mShownCount);
-            }
-        }
-    }
-
-    /**
-     * Fades out the long press tooltip if it's partially visible - short circuits any running
-     * animation. Additionally has the ability to fade in the status info text.
-     *
-     * @param shouldShowStatusText whether we should fade in the status text
-     */
-    private void hideLongPressTooltip(boolean shouldShowStatusText) {
-        mLongPressTooltipView.animate().cancel();
-        if (mLongPressTooltipView.getVisibility() == View.VISIBLE
-                && mLongPressTooltipView.getAlpha() != 0f) {
-            mHandler.removeCallbacks(mAutoFadeOutTooltipRunnable);
-            mLongPressTooltipView.animate()
-                    .alpha(0f)
-                    .setDuration(FADE_ANIMATION_DURATION_MS)
-                    .setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
-                            mLongPressTooltipView.setVisibility(View.INVISIBLE);
-
-                            if (shouldShowStatusText) {
-                                showStatus();
-                            }
-                        }
-                    })
-                    .start();
-        } else {
-            mLongPressTooltipView.setVisibility(View.INVISIBLE);
-            if (shouldShowStatusText) {
-                showStatus();
-            }
-        }
-    }
-
-    /**
-     * Fades in the updated status text. Note that if there's already a status showing, this will
-     * immediately fade it out and fade in the updated status.
-     */
-    private void showStatus() {
-        mStatusContainer.setAlpha(0f);
-
-        mStatusContainer.animate()
-                .alpha(1f)
-                .setDuration(FADE_ANIMATION_DURATION_MS)
-                .start();
-    }
-
-    /** Fades out the status text. */
-    private void hideStatusText() {
-        mStatusContainer.animate()
-                .alpha(0f)
-                .setDuration(FADE_ANIMATION_DURATION_MS)
-                .start();
-    }
-
     public void updateEverything() {
         post(() -> setClickable(!mExpanded));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ebafb81..c886062 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -54,7 +54,9 @@
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.util.wakelock.SettableWakeLock;
 import com.android.systemui.util.wakelock.WakeLock;
@@ -77,6 +79,8 @@
     private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300;
 
     private final Context mContext;
+    private final ShadeController mShadeController;
+    private final AccessibilityController mAccessibilityController;
     private ViewGroup mIndicationArea;
     private KeyguardIndicationTextView mTextView;
     private KeyguardIndicationTextView mDisclosure;
@@ -116,7 +120,9 @@
     public KeyguardIndicationController(Context context, ViewGroup indicationArea,
             LockIcon lockIcon) {
         this(context, indicationArea, lockIcon, new LockPatternUtils(context),
-                WakeLock.createPartial(context, "Doze:KeyguardIndication"));
+                WakeLock.createPartial(context, "Doze:KeyguardIndication"),
+                Dependency.get(ShadeController.class),
+                Dependency.get(AccessibilityController.class));
 
         registerCallbacks(KeyguardUpdateMonitor.getInstance(context));
     }
@@ -126,7 +132,8 @@
      */
     @VisibleForTesting
     KeyguardIndicationController(Context context, ViewGroup indicationArea, LockIcon lockIcon,
-            LockPatternUtils lockPatternUtils, WakeLock wakeLock) {
+            LockPatternUtils lockPatternUtils, WakeLock wakeLock, ShadeController shadeController,
+            AccessibilityController accessibilityController) {
         mContext = context;
         mIndicationArea = indicationArea;
         mTextView = indicationArea.findViewById(R.id.keyguard_indication_text);
@@ -134,9 +141,12 @@
                 mTextView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
         mDisclosure = indicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure);
         mLockIcon = lockIcon;
+        mShadeController = shadeController;
+        mAccessibilityController = accessibilityController;
         // lock icon is not used on all form factors.
         if (mLockIcon != null) {
-            mLockIcon.setOnLongClickListener(this::handleTrustCircleClick);
+            mLockIcon.setOnLongClickListener(this::handleLockLongClick);
+            mLockIcon.setOnClickListener(this::handleLockClick);
         }
         mWakeLock = new SettableWakeLock(wakeLock, TAG);
         mLockPatternUtils = lockPatternUtils;
@@ -173,7 +183,7 @@
         Dependency.get(StatusBarStateController.class).removeCallback(this);
     }
 
-    private boolean handleTrustCircleClick(View view) {
+    private boolean handleLockLongClick(View view) {
         mLockscreenGestureLogger.write(MetricsProto.MetricsEvent.ACTION_LS_LOCK,
                 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
         showTransientIndication(R.string.keyguard_indication_trust_disabled);
@@ -182,6 +192,13 @@
         return true;
     }
 
+    private void handleLockClick(View view) {
+        if (!mAccessibilityController.isAccessibilityEnabled()) {
+            return;
+        }
+        mShadeController.showBouncer(false /* scrimmed */);
+    }
+
     /**
      * Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this
      * {@link KeyguardIndicationController}.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 622b869..e6875e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -18,8 +18,7 @@
 
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -37,9 +36,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.graphics.Color;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
 import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -60,7 +57,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.logging.NotificationCounters;
 
 import java.util.List;
@@ -104,6 +100,8 @@
     private NotificationChannel mSingleNotificationChannel;
     private int mStartingChannelImportance;
     private boolean mWasShownHighPriority;
+    private boolean mShowOnLockscreen;
+    private boolean mShowInStatusBar;
     /**
      * The last importance level chosen by the user.  Null if the user has not chosen an importance
      * level; non-null once the user takes an action which indicates an explicit preference.
@@ -119,7 +117,8 @@
     private OnSettingsClickListener mOnSettingsClickListener;
     private OnAppSettingsClickListener mAppSettingsClickListener;
     private NotificationGuts mGutsContainer;
-    private GradientDrawable mSelectedBackground;
+    private Drawable mSelectedBackground;
+    private Drawable mUnselectedBackground;
 
     /** Whether this view is being shown as part of the blocking helper. */
     private boolean mIsForBlockingHelper;
@@ -133,6 +132,7 @@
     private OnClickListener mOnAlert = v -> {
         mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
         mChosenImportance = IMPORTANCE_DEFAULT;
+        setImportanceSummary(ACTION_ALERT);
         updateButtons(ACTION_ALERT);
     };
 
@@ -140,6 +140,7 @@
     private OnClickListener mOnSilent = v -> {
         mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
         mChosenImportance = IMPORTANCE_LOW;
+        setImportanceSummary(ACTION_TOGGLE_SILENT);
         updateButtons(ACTION_TOGGLE_SILENT);
     };
 
@@ -276,14 +277,8 @@
         mDelegatePkg = mSbn.getOpPkg();
         mIsDeviceProvisioned = isDeviceProvisioned;
 
-        mSelectedBackground = new GradientDrawable();
-        mSelectedBackground.setShape(GradientDrawable.RECTANGLE);
-        mSelectedBackground.setColor(mContext.getColor(R.color.notification_guts_selection_bg));
-        final float cornerRadii = getResources().getDisplayMetrics().density * 8;
-        mSelectedBackground.setCornerRadii(new float[]{cornerRadii, cornerRadii, cornerRadii,
-                cornerRadii, cornerRadii, cornerRadii, cornerRadii, cornerRadii});
-        mSelectedBackground.setStroke((int) (getResources().getDisplayMetrics().density * 2),
-                mContext.getColor(R.color.notification_guts_selection_border));
+        mSelectedBackground = mContext.getDrawable(R.drawable.button_border_selected);
+        mUnselectedBackground = mContext.getDrawable(R.drawable.button_border_unselected);
 
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
                 pkg, mAppUid, false /* includeDeleted */);
@@ -297,6 +292,10 @@
                     && numTotalChannels == 1;
         }
 
+        mShowInStatusBar = !mINotificationManager.shouldHideSilentStatusIcons(
+                mContext.getPackageName());
+        // TODO: b/128445911 use show on lockscreen setting
+
         bindHeader();
         bindChannelDetails();
 
@@ -334,6 +333,7 @@
             findViewById(R.id.non_configurable_text).setVisibility(VISIBLE);
             findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE);
             findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
+            ((TextView) findViewById(R.id.done)).setText(R.string.inline_done_button);
         } else if (mNumUniqueChannelsInRow > 1) {
             findViewById(R.id.non_configurable_text).setVisibility(GONE);
             findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
@@ -353,15 +353,17 @@
         done.setOnClickListener(mOnDismissSettings);
 
 
-        View silent = findViewById(R.id.silent_row);
-        View alert = findViewById(R.id.alert_row);
+        View silent = findViewById(R.id.silence);
+        View alert = findViewById(R.id.alert);
         silent.setOnClickListener(mOnSilent);
         alert.setOnClickListener(mOnAlert);
 
         if (mWasShownHighPriority) {
             updateButtons(ACTION_ALERT);
+            setImportanceSummary(ACTION_ALERT);
         } else {
             updateButtons(ACTION_TOGGLE_SILENT);
+            setImportanceSummary(ACTION_TOGGLE_SILENT);
         }
     }
 
@@ -482,14 +484,11 @@
             }
         }
         TextView groupNameView = findViewById(R.id.group_name);
-        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
         if (groupName != null) {
             groupNameView.setText(groupName);
             groupNameView.setVisibility(View.VISIBLE);
-            groupDividerView.setVisibility(View.VISIBLE);
         } else {
             groupNameView.setVisibility(View.GONE);
-            groupDividerView.setVisibility(View.GONE);
         }
     }
 
@@ -504,9 +503,9 @@
     private boolean hasImportanceChanged() {
         return mSingleNotificationChannel != null
                 && mChosenImportance != null
-                && (mStartingChannelImportance != mChosenImportance
-                || (mWasShownHighPriority && mChosenImportance < IMPORTANCE_DEFAULT)
-                || (!mWasShownHighPriority && mChosenImportance >= IMPORTANCE_DEFAULT));
+                && (mStartingChannelImportance == IMPORTANCE_UNSPECIFIED
+                        || (mWasShownHighPriority && mChosenImportance < IMPORTANCE_DEFAULT)
+                        || (!mWasShownHighPriority && mChosenImportance >= IMPORTANCE_DEFAULT));
     }
 
     private void saveImportance() {
@@ -526,29 +525,76 @@
         if (mChosenImportance != null) {
             mMetricsLogger.write(importanceChangeLogMaker());
 
+            int newImportance = mChosenImportance;
+            if (mStartingChannelImportance != IMPORTANCE_UNSPECIFIED) {
+                if ((mWasShownHighPriority && mChosenImportance >= IMPORTANCE_DEFAULT)
+                        || (!mWasShownHighPriority && mChosenImportance < IMPORTANCE_DEFAULT)) {
+                    newImportance = mStartingChannelImportance;
+                }
+            }
+
             Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
             bgHandler.post(
                     new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
                             mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
-                            mStartingChannelImportance, mChosenImportance));
+                            mStartingChannelImportance, newImportance));
         }
     }
 
     private void updateButtons(int blockState) {
-        View silent = findViewById(R.id.silent_row);
-        View alert = findViewById(R.id.alert_row);
+        TextView silence = findViewById(R.id.silence);
+        TextView alert = findViewById(R.id.alert);
+        TextView done = findViewById(R.id.done);
         switch (blockState) {
             case ACTION_TOGGLE_SILENT:
-                silent.setBackground(mSelectedBackground);
-                alert.setBackground(null);
+                updateButtons(silence, alert);
+                if (mWasShownHighPriority) {
+                    done.setText(R.string.inline_ok_button);
+                } else {
+                    done.setText(R.string.inline_done_button);
+                }
                 break;
             case ACTION_ALERT:
-                alert.setBackground(mSelectedBackground);
-                silent.setBackground(null);
+                updateButtons(alert, silence);
+                if (mWasShownHighPriority) {
+                    done.setText(R.string.inline_done_button);
+                } else {
+                    done.setText(R.string.inline_ok_button);
+                }
                 break;
         }
     }
 
+    private void updateButtons(TextView selected, TextView unselected) {
+        selected.setBackground(mSelectedBackground);
+        selected.setSelected(true);
+        selected.setTextAppearance(
+                R.style.TextAppearance_NotificationImportanceButton_Selected);
+        unselected.setBackground(mUnselectedBackground);
+        unselected.setSelected(false);
+        unselected.setTextAppearance(
+                R.style.TextAppearance_NotificationImportanceButton_Unselected);
+    }
+
+    void setImportanceSummary(int blockState) {
+        TextView view = findViewById(R.id.description);
+        if (blockState == ACTION_ALERT) {
+            view.setText(R.string.notification_channel_summary_default);
+        } else {
+            if (mShowInStatusBar) {
+                if (mShowOnLockscreen) {
+                    view.setText(R.string.notification_channel_summary_low_status_lock);
+                } else {
+                    view.setText(R.string.notification_channel_summary_low_status);
+                }
+            } else if (mShowOnLockscreen) {
+                view.setText(R.string.notification_channel_summary_low_lock);
+            } else {
+                view.setText(R.string.notification_channel_summary_low);
+            }
+        }
+    }
+
     private void saveImportanceAndExitReason(@NotificationInfoAction int action) {
         switch (action) {
             case ACTION_UNDO:
@@ -556,15 +602,8 @@
                 break;
             case ACTION_DELIVER_SILENTLY:
                 mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
-                mChosenImportance = IMPORTANCE_LOW;
-                break;
-            case ACTION_TOGGLE_SILENT:
-                mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
-                if (mWasShownHighPriority) {
-                    mChosenImportance = IMPORTANCE_LOW;
-                } else {
-                    mChosenImportance = IMPORTANCE_DEFAULT;
-                }
+                mChosenImportance = mWasShownHighPriority
+                        ? IMPORTANCE_LOW : mStartingChannelImportance;
                 break;
             default:
                 throw new IllegalArgumentException();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 6121ae6..586e82c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -248,10 +248,8 @@
         boolean canLock = mUnlockMethodCache.isMethodSecure()
                 && mUnlockMethodCache.canSkipBouncer();
         boolean clickToUnlock = mAccessibilityController.isAccessibilityEnabled();
-        boolean clickToForceLock = canLock && !clickToUnlock;
-        boolean longClickToForceLock = canLock && !clickToForceLock;
-        setClickable(clickToForceLock || clickToUnlock);
-        setLongClickable(longClickToForceLock);
+        setClickable(clickToUnlock);
+        setLongClickable(canLock && !clickToUnlock);
         setFocusable(mAccessibilityController.isAccessibilityEnabled());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 2a933a7..742fdda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -178,7 +178,7 @@
 
             // Send the assistant availability upon connection
             if (isConnected) {
-                mNavigationBarView.setAssistantAvailable(mAssistantAvailable);
+                sendAssistantAvailability(mAssistantAvailable);
             }
         }
 
@@ -235,7 +235,7 @@
             boolean available = mAssistManager
                     .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
             if (mAssistantAvailable != available) {
-                mNavigationBarView.setAssistantAvailable(available);
+                sendAssistantAvailability(available);
                 mAssistantAvailable = available;
             }
         }
@@ -903,6 +903,17 @@
         mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection);
     }
 
+    private void sendAssistantAvailability(boolean available) {
+        if (mOverviewProxyService.getProxy() != null) {
+            try {
+                mOverviewProxyService.getProxy().onAssistantAvailable(available
+                        && QuickStepContract.isGesturalMode(getContext()));
+            } catch (RemoteException e) {
+                Log.w(TAG, "Unable to send assistant availability data to launcher");
+            }
+        }
+    }
+
     // ----- Methods that DisplayNavigationBarController talks to -----
 
     /** Applies auto dimming animation on navigation bar when touched. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index a45d86e..411378f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -145,7 +145,6 @@
     private NotificationPanelView mPanelView;
 
     private NavBarTintController mTintController;
-    private boolean mAssistantAvailable;
 
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -759,23 +758,6 @@
         mEdgeBackGestureHandler.onOverlaysChanged();
     }
 
-    public void setAssistantAvailable(boolean available) {
-        mAssistantAvailable = available;
-        updateAssistantAvailability();
-    }
-
-    // TODO(b/112934365): move this back to NavigationBarFragment when prototype is removed
-    private void updateAssistantAvailability() {
-        boolean available = mAssistantAvailable && QuickStepContract.isGesturalMode(getContext());
-        if (mOverviewProxyService.getProxy() != null) {
-            try {
-                mOverviewProxyService.getProxy().onAssistantAvailable(available);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Unable to send assistant availability data to launcher");
-            }
-        }
-    }
-
     public void setMenuVisibility(final boolean show) {
         mContextualButtonGroup.setButtonVisiblity(R.id.menu, show);
     }
@@ -898,10 +880,6 @@
     public void showPinningEnterExitToast(boolean entering) {
         if (entering) {
             mScreenPinningNotify.showPinningStartToast();
-
-            // TODO(b/112934365): remove after prototype finished, only needed to escape from pin
-            getBackButton().setVisibility(VISIBLE);
-            getHomeButton().setVisibility(VISIBLE);
         } else {
             mScreenPinningNotify.showPinningExitToast();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 183fdb4..d5706e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -238,7 +238,8 @@
         mIconController.setIconVisibility(mSlotLocation, false);
 
         // sensors off
-        mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off, null);
+        mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off,
+                mContext.getString(R.string.accessibility_sensors_off_active));
         mIconController.setIconVisibility(mSlotSensorsOff,
                 mSensorPrivacyController.isSensorPrivacyEnabled());
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 3f33ba6..f08d7ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3326,7 +3326,11 @@
 
     @Override
     public void showBouncer(boolean scrimmed) {
-        mStatusBarKeyguardViewManager.showBouncer(scrimmed);
+        if (!mIsOccluded && !scrimmed && mState == StatusBarState.KEYGUARD) {
+            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+        } else {
+            mStatusBarKeyguardViewManager.showBouncer(scrimmed);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/tests/res/values/overlayable_icons_test.xml b/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
new file mode 100644
index 0000000..5cc7976
--- /dev/null
+++ b/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
@@ -0,0 +1,69 @@
+<!--
+   Copyright (C) 2019 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<resources>
+  <!-- overlayable_icons references all of the drawables in this package
+       that are being overlayed by resource overlays. If you remove/rename
+       any of these resources, you must also change the resource overlay icons.-->
+  <array name="overlayable_icons">
+    <item>@drawable/ic_alarm</item>
+    <item>@drawable/ic_alarm_dim</item>
+    <item>@drawable/ic_bluetooth_connected</item>
+    <item>@drawable/ic_brightness_thumb</item>
+    <item>@drawable/ic_camera</item>
+    <item>@drawable/ic_cast</item>
+    <item>@drawable/ic_cast_connected</item>
+    <item>@drawable/ic_close_white</item>
+    <item>@drawable/ic_data_saver</item>
+    <item>@drawable/ic_data_saver_off</item>
+    <item>@drawable/ic_drag_handle</item>
+    <item>@drawable/ic_headset</item>
+    <item>@drawable/ic_headset_mic</item>
+    <item>@drawable/ic_hotspot</item>
+    <item>@drawable/ic_info</item>
+    <item>@drawable/ic_info_outline</item>
+    <item>@drawable/ic_invert_colors</item>
+    <item>@drawable/ic_location</item>
+    <item>@drawable/ic_lockscreen_ime</item>
+    <item>@drawable/ic_notifications_alert</item>
+    <item>@drawable/ic_notifications_silence</item>
+    <item>@drawable/ic_power_low</item>
+    <item>@drawable/ic_power_saver</item>
+    <item>@drawable/ic_qs_bluetooth_connecting</item>
+    <item>@drawable/ic_qs_bluetooth_connecting</item>
+    <item>@drawable/ic_qs_cancel</item>
+    <item>@drawable/ic_qs_no_sim</item>
+    <item>@drawable/ic_qs_wifi_0</item>
+    <item>@drawable/ic_qs_wifi_1</item>
+    <item>@drawable/ic_qs_wifi_2</item>
+    <item>@drawable/ic_qs_wifi_3</item>
+    <item>@drawable/ic_qs_wifi_4</item>
+    <item>@drawable/ic_qs_wifi_disconnected</item>
+    <item>@drawable/ic_screenshot_delete</item>
+    <item>@drawable/ic_settings</item>
+    <item>@drawable/ic_swap_vert</item>
+    <item>@drawable/ic_tune_black_16dp</item>
+    <item>@drawable/ic_volume_alarm_mute</item>
+    <item>@drawable/ic_volume_bt_sco</item>
+    <item>@drawable/ic_volume_media</item>
+    <item>@drawable/ic_volume_media_mute</item>
+    <item>@drawable/ic_volume_ringer</item>
+    <item>@drawable/ic_volume_ringer_mute</item>
+    <item>@drawable/ic_volume_ringer_vibrate</item>
+    <item>@drawable/ic_volume_voice</item>
+    <item>@drawable/stat_sys_mic_none</item>
+    <item>@drawable/stat_sys_vpn_ic</item>
+  </array>
+</resources>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 80c51cf..375b6e54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -20,6 +20,8 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -46,11 +48,14 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -72,6 +77,10 @@
     private LockIcon mLockIcon;
     @Mock
     private LockPatternUtils mLockPatternUtils;
+    @Mock
+    private ShadeController mShadeController;
+    @Mock
+    private AccessibilityController mAccessibilityController;
     private KeyguardIndicationTextView mTextView;
 
     private KeyguardIndicationController mController;
@@ -102,7 +111,7 @@
             Looper.prepare();
         }
         mController = new KeyguardIndicationController(mContext, mIndicationArea, mLockIcon,
-                mLockPatternUtils, mWakeLock);
+                mLockPatternUtils, mWakeLock, mShadeController, mAccessibilityController);
     }
 
     @Test
@@ -222,4 +231,23 @@
         assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE);
         assertThat(mTextView.getAlpha()).isEqualTo(1f);
     }
+
+    @Test
+    public void lockIcon_click() {
+        createController();
+
+        ArgumentCaptor<View.OnLongClickListener> longClickCaptor = ArgumentCaptor.forClass(
+                View.OnLongClickListener.class);
+        ArgumentCaptor<View.OnClickListener> clickCaptor = ArgumentCaptor.forClass(
+                View.OnClickListener.class);
+        verify(mLockIcon).setOnLongClickListener(longClickCaptor.capture());
+        verify(mLockIcon).setOnClickListener(clickCaptor.capture());
+
+        when(mAccessibilityController.isAccessibilityEnabled()).thenReturn(true);
+        clickCaptor.getValue().onClick(mLockIcon);
+        verify(mShadeController).showBouncer(eq(false));
+
+        longClickCaptor.getValue().onLongClick(mLockIcon);
+        verify(mLockPatternUtils).requireCredentialEntry(anyInt());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index d2f8e02..02731c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -250,8 +250,6 @@
                 IMPORTANCE_DEFAULT, true);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(GONE, groupNameView.getVisibility());
-        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
-        assertEquals(GONE, groupDividerView.getVisibility());
     }
 
     @Test
@@ -268,8 +266,6 @@
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(View.VISIBLE, groupNameView.getVisibility());
         assertEquals("Test Group Name", groupNameView.getText());
-        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
-        assertEquals(View.VISIBLE, groupDividerView.getVisibility());
     }
 
     @Test
@@ -486,7 +482,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.alert).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -500,7 +496,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.silent_row).performClick();
+        mNotificationInfo.findViewById(R.id.silence).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -527,7 +523,7 @@
         mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
+                IMPORTANCE_UNSPECIFIED, true);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -542,6 +538,7 @@
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
@@ -570,6 +567,7 @@
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
@@ -588,6 +586,7 @@
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
                 mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
@@ -603,6 +602,7 @@
 
     @Test
     public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
                 mMockINotificationManager,
@@ -629,7 +629,7 @@
     @Test
     public void testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper()
             throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
                 mMockINotificationManager,
@@ -644,7 +644,7 @@
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
                 IMPORTANCE_DEFAULT,
-                false);
+                true);
 
         mNotificationInfo.findViewById(R.id.deliver_silently).performClick();
         waitForUndoButton();
@@ -684,7 +684,7 @@
         mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                IMPORTANCE_DEFAULT, false);
+                IMPORTANCE_DEFAULT, true);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -704,7 +704,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.silent_row).performClick();
+        mNotificationInfo.findViewById(R.id.silence).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -723,9 +723,9 @@
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
+                IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -745,9 +745,9 @@
         mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
+                IMPORTANCE_UNSPECIFIED, true);
 
-        mNotificationInfo.findViewById(R.id.silent_row).performClick();
+        mNotificationInfo.findViewById(R.id.silence).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -762,14 +762,82 @@
     }
 
     @Test
-    public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+    public void testSilenceCallsUpdateNotificationChannel_channelImportanceMin()
             throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationChannel.setImportance(IMPORTANCE_MIN);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                IMPORTANCE_MIN, false);
+
+        assertEquals(mContext.getString(R.string.inline_done_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.silence).performClick();
+        assertEquals(mContext.getString(R.string.inline_done_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.done).performClick();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()& USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testAlertCallsUpdateNotificationChannel_channelImportanceMin()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_MIN);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                IMPORTANCE_MIN, false);
+
+        assertEquals(mContext.getString(R.string.inline_done_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.alert).performClick();
+        assertEquals(mContext.getString(R.string.inline_ok_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.done).performClick();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()& USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testDoneText()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        assertEquals(mContext.getString(R.string.inline_done_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.alert).performClick();
+        assertEquals(mContext.getString(R.string.inline_ok_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+        mNotificationInfo.findViewById(R.id.silence).performClick();
+        assertEquals(mContext.getString(R.string.inline_done_button),
+                ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
+    }
+
+    @Test
+    public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                IMPORTANCE_LOW, false);
+
+        mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -790,7 +858,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(false, false);
 
@@ -809,7 +877,7 @@
                 }, null, null, true, false, IMPORTANCE_LOW, false
         );
 
-        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
diff --git a/packages/overlays/IconShapeSquareOverlay/res/values/config.xml b/packages/overlays/IconShapeSquareOverlay/res/values/config.xml
index 7b65555..2016ece 100644
--- a/packages/overlays/IconShapeSquareOverlay/res/values/config.xml
+++ b/packages/overlays/IconShapeSquareOverlay/res/values/config.xml
@@ -23,6 +23,8 @@
     <bool name="config_useRoundIcon">false</bool>
     <!-- Corner radius of system dialogs -->
     <dimen name="config_dialogCornerRadius">0dp</dimen>
-
+    <!-- Corner radius for bottom sheet system dialogs -->
+    <dimen name="config_bottomDialogCornerRadius">0dp</dimen>
+  
 </resources>
 
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index bf76fdb..21c6035 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7197,6 +7197,15 @@
     // OS: Q
     DIALOG_PREFERRED_SIM_PICKER = 1709;
 
+    // ACTION: Share a Wi-Fi network by generating a QR code
+    ACTION_SETTINGS_SHARE_WIFI_QR_CODE = 1710;
+
+    // ACTION: Connect to a Wi-Fi network by scanning a QR code
+    ACTION_SETTINGS_ENROLL_WIFI_QR_CODE = 1711;
+
+    // ACTION: Share Wi-Fi hotspot by generating a QR code
+    ACTION_SETTINGS_SHARE_WIFI_HOTSPOT_QR_CODE = 1712;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 334262f..05b937a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2722,9 +2722,7 @@
         return -1;
     }
 
-    private void notifyOutsideTouchIfNeeded(int targetWindowId, int action, Bundle arguments,
-            int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
-            int interrogatingPid, long interrogatingTid) {
+    private void notifyOutsideTouchIfNeeded(int targetWindowId, int action) {
         if (action != ACTION_CLICK && action != ACTION_LONG_CLICK) {
             return;
         }
@@ -2741,13 +2739,10 @@
             final RemoteAccessibilityConnection connection = connectionList.get(i);
             if (connection != null) {
                 try {
-                    connection.mConnection.performAccessibilityAction(
-                            AccessibilityNodeInfo.ROOT_ITEM_ID,
-                            R.id.accessibilityActionOutsideTouch, arguments, interactionId,
-                            callback, fetchFlags, interrogatingPid, interrogatingTid);
+                    connection.getRemote().notifyOutsideTouch();
                 } catch (RemoteException re) {
                     if (DEBUG) {
-                        Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
+                        Slog.e(LOG_TAG, "Error calling notifyOutsideTouch()");
                     }
                 }
             }
@@ -2833,8 +2828,7 @@
             mPowerManager.userActivity(SystemClock.uptimeMillis(),
                     PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
 
-            notifyOutsideTouchIfNeeded(resolvedWindowId, action, arguments, interactionId, callback,
-                    fetchFlags, interrogatingPid, interrogatingTid);
+            notifyOutsideTouchIfNeeded(resolvedWindowId, action);
             if (activityToken != null) {
                 LocalServices.getService(ActivityTaskManagerInternal.class)
                         .setFocusedActivity(activityToken);
@@ -3790,7 +3784,7 @@
 
         private List<Integer> getWatchOutsideTouchWindowIdLocked(int targetWindowId) {
             final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
-            if (targetWindow != null && mWindowInfoById != null && mHasWatchOutsideTouchWindow) {
+            if (targetWindow != null && mHasWatchOutsideTouchWindow) {
                 final List<Integer> outsideWindowsId = new ArrayList<>();
                 for (int i = 0; i < mWindowInfoById.size(); i++) {
                     WindowInfo window = mWindowInfoById.valueAt(i);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6c3a169..ee8bb05 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -735,19 +735,18 @@
                 }
             }
 
-            final DetailedState state = DetailedState.DISCONNECTED;
-
             if (wasFirstNetwork || wasDefault) {
-                maybeLogBroadcast(nai, state, type, wasDefault);
-                mService.sendLegacyNetworkBroadcast(nai, state, type);
+                maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault);
+                mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type);
             }
 
             if (!list.isEmpty() && wasFirstNetwork) {
                 if (DBG) log("Other network available for type " + type +
                               ", sending connected broadcast");
                 final NetworkAgentInfo replacement = list.get(0);
-                maybeLogBroadcast(replacement, state, type, mService.isDefaultNetwork(replacement));
-                mService.sendLegacyNetworkBroadcast(replacement, state, type);
+                maybeLogBroadcast(replacement, DetailedState.CONNECTED, type,
+                        mService.isDefaultNetwork(replacement));
+                mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type);
             }
         }
 
@@ -2812,6 +2811,11 @@
                     EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
                     mNai.network.netId));
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 
     private boolean networkRequiresValidation(NetworkAgentInfo nai) {
diff --git a/services/core/java/com/android/server/ExtconUEventObserver.java b/services/core/java/com/android/server/ExtconUEventObserver.java
index 6b42b3d..5bd27c4 100644
--- a/services/core/java/com/android/server/ExtconUEventObserver.java
+++ b/services/core/java/com/android/server/ExtconUEventObserver.java
@@ -159,7 +159,13 @@
         }
     }
 
-    /** Does the {@link /sys/class/extcon} directory exist */
+    /** Does the {@code /sys/class/extcon/<name>} directory exist */
+    public static boolean namedExtconDirExists(String name) {
+        File extconDir = new File("/sys/class/extcon/" + name);
+        return extconDir.exists() && extconDir.isDirectory();
+    }
+
+    /** Does the {@code /sys/class/extcon} directory exist */
     public static boolean extconExists() {
         File extconDir = new File("/sys/class/extcon");
         return extconDir.exists() && extconDir.isDirectory();
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 236797b..5255316 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -407,6 +407,7 @@
         SynchronousResultReceiver wifiReceiver = null;
         SynchronousResultReceiver bluetoothReceiver = null;
         SynchronousResultReceiver modemReceiver = null;
+        boolean railUpdated = false;
 
         if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
             // We were asked to fetch WiFi data.
@@ -426,6 +427,10 @@
                     // Oh well.
                 }
             }
+            synchronized (mStats) {
+                mStats.updateRailStatsLocked();
+            }
+            railUpdated = true;
         }
 
         if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
@@ -447,6 +452,11 @@
                 modemReceiver = new SynchronousResultReceiver("telephony");
                 mTelephony.requestModemActivityInfo(modemReceiver);
             }
+            if (!railUpdated) {
+                synchronized (mStats) {
+                    mStats.updateRailStatsLocked();
+                }
+            }
         }
 
         final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
@@ -477,10 +487,6 @@
                 mStats.updateRpmStatsLocked();
             }
 
-            if ((updateFlags & UPDATE_RAIL) != 0) {
-                mStats.updateRailStatsLocked();
-            }
-
             if (bluetoothInfo != null) {
                 if (bluetoothInfo.isValid()) {
                     mStats.updateBluetoothStateLocked(bluetoothInfo);
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 99380c9..19c3a71 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -132,16 +132,20 @@
         }
 
         for (String deviceConfigScope : mDeviceConfigScopes) {
-            DeviceConfig.addOnPropertyChangedListener(
+            DeviceConfig.addOnPropertiesChangedListener(
                     deviceConfigScope,
                     AsyncTask.THREAD_POOL_EXECUTOR,
-                    (String scope, String name, String value) -> {
-                        String propertyName = makePropertyName(scope, name);
-                        if (propertyName == null) {
-                            log("unable to construct system property for " + scope + "/" + name);
-                            return;
+                    (DeviceConfig.Properties properties) -> {
+                        String scope = properties.getNamespace();
+                        for (String key : properties.getKeyset()) {
+                            String propertyName = makePropertyName(scope, key);
+                            if (propertyName == null) {
+                                log("unable to construct system property for " + scope + "/"
+                                        + key);
+                                return;
+                            }
+                            setProperty(propertyName, properties.getString(key, null));
                         }
-                        setProperty(propertyName, value);
                     });
         }
     }
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index f198464..d56cb79 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -46,26 +46,12 @@
   ],
   "postsubmit": [
     {
-      "name": "CtsActivityManagerDeviceTestCases"
-    },
-    {
-      "name": "CtsActivityManagerDeviceSdk25TestCases"
-    },
-    {
       "name": "FrameworksServicesTests",
       "options": [
         {
           "include-filter": "com.android.server.am."
         }
       ]
-    },
-    {
-      "name": "WmTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.am."
-        }
-      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index e218c6b..44fd846 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -23,7 +23,12 @@
 
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
@@ -48,10 +53,10 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.DumpUtils;
@@ -124,6 +129,49 @@
             // but let's leave it as-is for now.
             return result || !authenticated;
         }
+
+        @Override
+        public boolean onAcquired(int acquireInfo, int vendorCode) {
+
+            if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
+                final String name =
+                        getContext().getString(R.string.face_recalibrate_notification_name);
+                final String title =
+                        getContext().getString(R.string.face_recalibrate_notification_title);
+                final String content =
+                        getContext().getString(R.string.face_recalibrate_notification_content);
+
+                final Intent intent = new Intent("android.settings.FACE_SETTINGS");
+                intent.setPackage("com.android.settings");
+
+                final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(),
+                        0 /* requestCode */, intent, 0 /* flags */, null /* options */,
+                        UserHandle.CURRENT);
+
+                final String id = "FaceService";
+
+                NotificationManager nm =
+                        getContext().getSystemService(NotificationManager.class);
+                NotificationChannel channel = new NotificationChannel(id, name,
+                        NotificationManager.IMPORTANCE_HIGH);
+                Notification notification = new Notification.Builder(getContext(), id)
+                        .setSmallIcon(R.drawable.ic_lock)
+                        .setContentTitle(title)
+                        .setContentText(content)
+                        .setSubText(name)
+                        .setOnlyAlertOnce(true)
+                        .setLocalOnly(true)
+                        .setAutoCancel(true)
+                        .setCategory(Notification.CATEGORY_SYSTEM)
+                        .setContentIntent(pendingIntent)
+                        .build();
+
+                nm.createNotificationChannel(channel);
+                nm.notifyAsUser(null /* tag */, 0 /* id */, notification, UserHandle.CURRENT);
+            }
+
+            return super.onAcquired(acquireInfo, vendorCode);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 1913635..e33392d 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -34,6 +34,7 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkUtils;
+import android.net.ResolverParamsParcel;
 import android.net.Uri;
 import android.net.shared.PrivateDnsConfig;
 import android.os.Binder;
@@ -311,11 +312,9 @@
 
     public void setDnsConfigurationForNetwork(
             int netId, LinkProperties lp, boolean isDefaultNetwork) {
-        final String[] assignedServers = NetworkUtils.makeStrings(lp.getDnsServers());
-        final String[] domainStrs = getDomainStrings(lp.getDomains());
 
         updateParametersSettings();
-        final int[] params = { mSampleValidity, mSuccessThreshold, mMinSamples, mMaxSamples };
+        final ResolverParamsParcel paramsParcel = new ResolverParamsParcel();
 
         // We only use the PrivateDnsConfig data pushed to this class instance
         // from ConnectivityService because it works in coordination with
@@ -329,34 +328,44 @@
 
         final boolean useTls = privateDnsCfg.useTls;
         final boolean strictMode = privateDnsCfg.inStrictMode();
-        final String tlsHostname = strictMode ? privateDnsCfg.hostname : "";
-        final String[] tlsServers =
+        paramsParcel.netId = netId;
+        paramsParcel.sampleValiditySeconds = mSampleValidity;
+        paramsParcel.successThreshold = mSuccessThreshold;
+        paramsParcel.minSamples = mMinSamples;
+        paramsParcel.maxSamples = mMaxSamples;
+        paramsParcel.servers = NetworkUtils.makeStrings(lp.getDnsServers());
+        paramsParcel.domains = getDomainStrings(lp.getDomains());
+        paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : "";
+        paramsParcel.tlsServers =
                 strictMode ? NetworkUtils.makeStrings(
                         Arrays.stream(privateDnsCfg.ips)
                               .filter((ip) -> lp.isReachable(ip))
                               .collect(Collectors.toList()))
-                : useTls ? assignedServers  // Opportunistic
+                : useTls ? paramsParcel.servers  // Opportunistic
                 : new String[0];            // Off
-
+        paramsParcel.tlsFingerprints = new String[0];
         // Prepare to track the validation status of the DNS servers in the
         // resolver config when private DNS is in opportunistic or strict mode.
         if (useTls) {
             if (!mPrivateDnsValidationMap.containsKey(netId)) {
                 mPrivateDnsValidationMap.put(netId, new PrivateDnsValidationStatuses());
             }
-            mPrivateDnsValidationMap.get(netId).updateTrackedDnses(tlsServers, tlsHostname);
+            mPrivateDnsValidationMap.get(netId).updateTrackedDnses(paramsParcel.tlsServers,
+                    paramsParcel.tlsName);
         } else {
             mPrivateDnsValidationMap.remove(netId);
         }
 
-        Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)",
-                netId, Arrays.toString(assignedServers), Arrays.toString(domainStrs),
-                Arrays.toString(params), tlsHostname, Arrays.toString(tlsServers)));
-        final String[] tlsFingerprints = new String[0];
+        Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
+                + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers),
+                Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds,
+                paramsParcel.successThreshold, paramsParcel.minSamples,
+                paramsParcel.maxSamples, paramsParcel.baseTimeoutMsec,
+                paramsParcel.retryCount, paramsParcel.tlsName,
+                Arrays.toString(paramsParcel.tlsServers)));
+
         try {
-            mDnsResolver.setResolverConfiguration(
-                    netId, assignedServers, domainStrs, params,
-                    tlsHostname, tlsServers, tlsFingerprints);
+            mDnsResolver.setResolverConfiguration(paramsParcel);
         } catch (RemoteException | ServiceSpecificException e) {
             Slog.e(TAG, "Error setting DNS configuration: " + e);
             return;
diff --git a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java b/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java
index b4b6160..88ff6e7 100644
--- a/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java
+++ b/services/core/java/com/android/server/location/GnssCapabilitiesProvider.java
@@ -28,33 +28,16 @@
     private static final String TAG = "GnssCapabilitiesProvider";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    // Bit masks for capabilities in {@link android.location.GnssCapabilities}.
-    private static final long GNSS_CAPABILITY_LOW_POWER_MODE =
-            1L << GnssCapabilities.LOW_POWER_MODE;
-    private static final long GNSS_CAPABILITY_SATELLITE_BLACKLIST =
-            1L << GnssCapabilities.SATELLITE_BLACKLIST;
-    private static final long GNSS_CAPABILITY_GEOFENCING = 1L << GnssCapabilities.GEOFENCING;
-    private static final long GNSS_CAPABILITY_MEASUREMENTS = 1L << GnssCapabilities.MEASUREMENTS;
-    private static final long GNSS_CAPABILITY_NAV_MESSAGES = 1L << GnssCapabilities.NAV_MESSAGES;
-    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS =
-            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS;
-    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS =
-            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_LOS_SATS;
-    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH =
-            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH;
-    private static final long GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE =
-            1L << GnssCapabilities.MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
-
     private static final long GNSS_CAPABILITIES_TOP_HAL =
-            GNSS_CAPABILITY_LOW_POWER_MODE | GNSS_CAPABILITY_SATELLITE_BLACKLIST
-                    | GNSS_CAPABILITY_GEOFENCING | GNSS_CAPABILITY_MEASUREMENTS
-                    | GNSS_CAPABILITY_NAV_MESSAGES;
+            GnssCapabilities.LOW_POWER_MODE | GnssCapabilities.SATELLITE_BLACKLIST
+                    | GnssCapabilities.GEOFENCING | GnssCapabilities.MEASUREMENTS
+                    | GnssCapabilities.NAV_MESSAGES;
 
     private static final long GNSS_CAPABILITIES_SUB_HAL_MEASUREMENT_CORRECTIONS =
-            GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS
-                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS
-                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH
-                    | GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
+            GnssCapabilities.MEASUREMENT_CORRECTIONS
+                    | GnssCapabilities.MEASUREMENT_CORRECTIONS_LOS_SATS
+                    | GnssCapabilities.MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH
+                    | GnssCapabilities.MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
 
     // Capabilities in {@link android.location.GnssCapabilities} supported by GNSS chipset.
     @GuardedBy("this")
@@ -79,20 +62,20 @@
         long gnssCapabilities = 0;
         if (hasCapability(topHalCapabilities,
                 GnssLocationProvider.GPS_CAPABILITY_LOW_POWER_MODE)) {
-            gnssCapabilities |= GNSS_CAPABILITY_LOW_POWER_MODE;
+            gnssCapabilities |= GnssCapabilities.LOW_POWER_MODE;
         }
         if (hasCapability(topHalCapabilities,
                 GnssLocationProvider.GPS_CAPABILITY_SATELLITE_BLACKLIST)) {
-            gnssCapabilities |= GNSS_CAPABILITY_SATELLITE_BLACKLIST;
+            gnssCapabilities |= GnssCapabilities.SATELLITE_BLACKLIST;
         }
         if (hasCapability(topHalCapabilities, GnssLocationProvider.GPS_CAPABILITY_GEOFENCING)) {
-            gnssCapabilities |= GNSS_CAPABILITY_GEOFENCING;
+            gnssCapabilities |= GnssCapabilities.GEOFENCING;
         }
         if (hasCapability(topHalCapabilities, GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS)) {
-            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENTS;
+            gnssCapabilities |= GnssCapabilities.MEASUREMENTS;
         }
         if (hasCapability(topHalCapabilities, GnssLocationProvider.GPS_CAPABILITY_NAV_MESSAGES)) {
-            gnssCapabilities |= GNSS_CAPABILITY_NAV_MESSAGES;
+            gnssCapabilities |= GnssCapabilities.NAV_MESSAGES;
         }
 
         synchronized (this) {
@@ -110,18 +93,18 @@
      * {@link android.location.GnssCapabilities}.
      */
     void setSubHalMeasurementCorrectionsCapabilities(int measurementCorrectionsCapabilities) {
-        long gnssCapabilities = GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS;
+        long gnssCapabilities = GnssCapabilities.MEASUREMENT_CORRECTIONS;
         if (hasCapability(measurementCorrectionsCapabilities,
                 GnssMeasurementCorrectionsProvider.CAPABILITY_LOS_SATS)) {
-            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_LOS_SATS;
+            gnssCapabilities |= GnssCapabilities.MEASUREMENT_CORRECTIONS_LOS_SATS;
         }
         if (hasCapability(measurementCorrectionsCapabilities,
                 GnssMeasurementCorrectionsProvider.CAPABILITY_EXCESS_PATH_LENGTH)) {
-            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH;
+            gnssCapabilities |= GnssCapabilities.MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH;
         }
         if (hasCapability(measurementCorrectionsCapabilities,
                 GnssMeasurementCorrectionsProvider.CAPABILITY_REFLECTING_PLANE)) {
-            gnssCapabilities |= GNSS_CAPABILITY_MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
+            gnssCapabilities |= GnssCapabilities.MEASUREMENT_CORRECTIONS_REFLECTING_PLANE;
         }
 
         synchronized (this) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ec0f8b8..d93dddfc 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2215,7 +2215,7 @@
             s.append("MEASUREMENT_CORRECTIONS ");
         }
         s.append(")\n");
-        if (mGnssMeasurementCorrectionsProvider.isAvailableInPlatform()) {
+        if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
             s.append("  SubHal=MEASUREMENT_CORRECTIONS[");
             s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities());
             s.append("]\n");
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index 60be70e..8391f9d 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -288,6 +288,18 @@
                     return "<Unknown>";
             }
         }
+
+        private boolean isRequestAccepted() {
+            return mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED;
+        }
+
+        private boolean isRequestAttributedToProxyApp() {
+            return !TextUtils.isEmpty(mProxyAppPackageName);
+        }
+
+        private boolean isEmergencyRequestNotification() {
+            return mInEmergencyMode && !isRequestAttributedToProxyApp();
+        }
     }
 
     private void handlePermissionsChanged(int uid) {
@@ -376,20 +388,37 @@
     private void handleNfwNotification(NfwNotification nfwNotification) {
         if (DEBUG) Log.d(TAG, "Non-framework location access notification: " + nfwNotification);
 
-        final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
-        Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
-                proxyAppPackageName);
-        boolean isLocationRequestAccepted =
-                nfwNotification.mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED;
-        boolean isPermissionMismatched;
-        if (isLocationPermissionEnabled == null) {
-            isPermissionMismatched = isLocationRequestAccepted;
-        } else {
-            isPermissionMismatched = (isLocationPermissionEnabled != isLocationRequestAccepted);
+        if (nfwNotification.isEmergencyRequestNotification()) {
+            handleEmergencyNfwNotification(nfwNotification);
+            return;
         }
+
+        final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
+        final Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
+                proxyAppPackageName);
+        final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
+        final boolean isPermissionMismatched =
+                (isLocationPermissionEnabled == null) ? isLocationRequestAccepted
+                        : (isLocationPermissionEnabled != isLocationRequestAccepted);
         logEvent(nfwNotification, isPermissionMismatched);
 
-        if (TextUtils.isEmpty(proxyAppPackageName)) {
+        if (!nfwNotification.isRequestAttributedToProxyApp()) {
+            // Handle cases where GNSS HAL implementation correctly rejected NFW location request.
+            // 1. GNSS HAL implementation doesn't provide location to any NFW location use cases.
+            //    There is no Location Attribution App configured in the framework.
+            // 2. GNSS HAL implementation doesn't provide location to some NFW location use cases.
+            //    Location Attribution Apps are configured only for the supported NFW location
+            //    use cases. All other use cases which are not supported (and always rejected) by
+            //    the GNSS HAL implementation will have proxyAppPackageName set to empty string.
+            if (!isLocationRequestAccepted) {
+                if (DEBUG) {
+                    Log.d(TAG, "Non-framework location request rejected. ProxyAppPackageName field"
+                            + " is not set in the notification: " + nfwNotification + ". Number of"
+                            + " configured proxy apps: " + mProxyAppToLocationPermissions.size());
+                }
+                return;
+            }
+
             Log.e(TAG, "ProxyAppPackageName field is not set. AppOps service not notified "
                     + "for non-framework location access notification: " + nfwNotification);
             return;
@@ -423,6 +452,16 @@
         }
     }
 
+    private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
+        boolean isPermissionMismatched =
+                (nfwNotification.mResponseType == NfwNotification.NFW_RESPONSE_TYPE_REJECTED);
+        if (isPermissionMismatched) {
+            Log.e(TAG, "Emergency non-framework location request incorrectly rejected."
+                    + " Notification: " + nfwNotification);
+        }
+        logEvent(nfwNotification, isPermissionMismatched);
+    }
+
     private void logEvent(NfwNotification notification, boolean isPermissionMismatched) {
         StatsLog.write(StatsLog.GNSS_NFW_NOTIFICATION_REPORTED,
                 notification.mProxyAppPackageName,
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index af299cf..69efd02 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -24,10 +24,14 @@
 import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
 
 import android.annotation.Nullable;
+import android.net.INetd;
 import android.net.NetworkStats;
+import android.net.util.NetdService;
+import android.os.RemoteException;
 import android.os.StrictMode;
 import android.os.SystemClock;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ProcFileReader;
@@ -64,7 +68,10 @@
 
     private boolean mUseBpfStats;
 
+    private INetd mNetdService;
+
     // A persistent Snapshot since device start for eBPF stats
+    @GuardedBy("mPersistSnapshot")
     private final NetworkStats mPersistSnapshot;
 
     // TODO: only do adjustments in NetworkStatsService and remove this.
@@ -272,6 +279,19 @@
         return stats;
     }
 
+    @GuardedBy("mPersistSnapshot")
+    private void requestSwapActiveStatsMapLocked() throws RemoteException {
+        // Ask netd to do a active map stats swap. When the binder call successfully returns,
+        // the system server should be able to safely read and clean the inactive map
+        // without race problem.
+        if (mUseBpfStats) {
+            if (mNetdService == null) {
+                mNetdService = NetdService.getInstance();
+            }
+            mNetdService.trafficSwapActiveStatsMap();
+        }
+    }
+
     // TODO: delete the lastStats parameter
     private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces,
             int limitTag, NetworkStats lastStats) throws IOException {
@@ -284,15 +304,24 @@
                 stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
             }
             if (mUseBpfStats) {
-                if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
-                        null, TAG_ALL, mUseBpfStats) != 0) {
-                    throw new IOException("Failed to parse network stats");
+                synchronized (mPersistSnapshot) {
+                    try {
+                        requestSwapActiveStatsMapLocked();
+                    } catch (RemoteException e) {
+                        throw new IOException(e);
+                    }
+                    // Stats are always read from the inactive map, so they must be read after the
+                    // swap
+                    if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
+                            null, TAG_ALL, mUseBpfStats) != 0) {
+                        throw new IOException("Failed to parse network stats");
+                    }
+                    mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
+                    mPersistSnapshot.combineAllValues(stats);
+                    NetworkStats result = mPersistSnapshot.clone();
+                    result.filter(limitUid, limitIfaces, limitTag);
+                    return result;
                 }
-                mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
-                mPersistSnapshot.combineAllValues(stats);
-                NetworkStats result = mPersistSnapshot.clone();
-                result.filter(limitUid, limitIfaces, limitTag);
-                return result;
             } else {
                 if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
                         limitIfaces, limitTag, mUseBpfStats) != 0) {
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index b85abd9..61be1f5 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -46,6 +46,7 @@
             int notificationLocation);
     void onNotificationDirectReplied(String key);
     void onNotificationSettingsViewed(String key);
+    void onNotificationBubbleChanged(String key, boolean isBubble);
 
     /**
      * Notifies that smart replies and actions have been added to the UI.
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e5ecd49..9fc30eb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1020,6 +1020,24 @@
                 }
             }
         }
+
+        @Override
+        public void onNotificationBubbleChanged(String key, boolean isBubble) {
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r != null) {
+                    final StatusBarNotification n = r.sbn;
+                    final int callingUid = n.getUid();
+                    final String pkg = n.getPackageName();
+                    if (isBubble && isNotificationAppropriateToBubble(r, pkg, callingUid,
+                            null /* oldEntry */)) {
+                        r.getNotification().flags |= FLAG_BUBBLE;
+                    } else {
+                        r.getNotification().flags &= ~FLAG_BUBBLE;
+                    }
+                }
+            }
+        }
     };
 
     @VisibleForTesting
@@ -4782,6 +4800,19 @@
     private void flagNotificationForBubbles(NotificationRecord r, String pkg, int userId,
             NotificationRecord oldRecord) {
         Notification notification = r.getNotification();
+        if (isNotificationAppropriateToBubble(r, pkg, userId, oldRecord)) {
+            notification.flags |= FLAG_BUBBLE;
+        } else {
+            notification.flags &= ~FLAG_BUBBLE;
+        }
+    }
+
+    /**
+     * @return whether the provided notification record is allowed to be represented as a bubble.
+     */
+    private boolean isNotificationAppropriateToBubble(NotificationRecord r, String pkg, int userId,
+            NotificationRecord oldRecord) {
+        Notification notification = r.getNotification();
 
         // Does the app want to bubble & have permission to bubble?
         boolean canBubble = notification.getBubbleMetadata() != null
@@ -4807,12 +4838,7 @@
         // OR something that was previously a bubble & still exists
         boolean bubbleUpdate = oldRecord != null
                 && (oldRecord.getNotification().flags & FLAG_BUBBLE) != 0;
-
-        if (canBubble && (notificationAppropriateToBubble || appIsForeground || bubbleUpdate)) {
-            notification.flags |= FLAG_BUBBLE;
-        } else {
-            notification.flags &= ~FLAG_BUBBLE;
-        }
+        return canBubble && (notificationAppropriateToBubble || appIsForeground || bubbleUpdate);
     }
 
     private void doChannelWarningToast(CharSequence toastText) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3c336ea..a25f8c0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -598,6 +598,8 @@
 
     private static final String ODM_OVERLAY_DIR = "/odm/overlay";
 
+    private static final String OEM_OVERLAY_DIR = "/oem/overlay";
+
     /** Canonical intent used to identify what counts as a "web browser" app */
     private static final Intent sBrowserIntent;
     static {
@@ -2631,6 +2633,13 @@
                     | SCAN_AS_SYSTEM
                     | SCAN_AS_ODM,
                     0);
+            scanDirTracedLI(new File(OEM_OVERLAY_DIR),
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_OEM,
+                    0);
 
             mParallelPackageParserCallback.findStaticOverlayPackages();
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 6b804df..33dd48a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -25,6 +25,8 @@
 import android.accounts.IAccountManager;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.role.IRoleManager;
+import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -75,6 +77,7 @@
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
 import android.os.PersistableBundle;
 import android.os.Process;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ShellCommand;
@@ -115,6 +118,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.WeakHashMap;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -2460,19 +2464,37 @@
             }
         }
 
+        String pkgName;
         String component = getNextArg();
-        ComponentName componentName =
-                component != null ? ComponentName.unflattenFromString(component) : null;
-
-        if (componentName == null) {
-            pw.println("Error: component name not specified or invalid");
-            return 1;
+        if (component.indexOf('/') < 0) {
+            // No component specified, so assume it's just a package name.
+            pkgName = component;
+        } else {
+            ComponentName componentName =
+                    component != null ? ComponentName.unflattenFromString(component) : null;
+            if (componentName == null) {
+                pw.println("Error: invalid component name");
+                return 1;
+            }
+            pkgName = componentName.getPackageName();
         }
 
+
+        final CompletableFuture<Boolean> future = new CompletableFuture<>();
+        final RemoteCallback callback = new RemoteCallback(res -> future.complete(res != null));
         try {
-            mInterface.setHomeActivity(componentName, userId);
-            pw.println("Success");
-            return 0;
+            IRoleManager roleManager = android.app.role.IRoleManager.Stub.asInterface(
+                    ServiceManager.getServiceOrThrow(Context.ROLE_SERVICE));
+            roleManager.addRoleHolderAsUser(RoleManager.ROLE_HOME, pkgName,
+                    0, userId, callback);
+            boolean success = future.get();
+            if (success) {
+                pw.println("Success");
+                return 0;
+            } else {
+                pw.println("Error: Failed to set default home.");
+                return 1;
+            }
         } catch (Exception e) {
             pw.println(e.toString());
             return 1;
@@ -3161,6 +3183,10 @@
         pw.println("");
         pw.println("  set-home-activity [--user USER_ID] TARGET-COMPONENT");
         pw.println("    Set the default home activity (aka launcher).");
+        pw.println("    TARGET-COMPONENT can be a package name (com.package.my) or a full");
+        pw.println("    component (com.package.my/component.name). However, only the package name");
+        pw.println("    matters: the actual component used will be determined automatically from");
+        pw.println("    the package.");
         pw.println("");
         pw.println("  set-installer PACKAGE INSTALLER");
         pw.println("    Set installer package name");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9b4293d48..d624a85 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -310,6 +310,7 @@
     static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
     static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
 
+    private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
     private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
             .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
@@ -615,6 +616,8 @@
     private boolean mPerDisplayFocusEnabled = false;
     private volatile int mTopFocusedDisplayId = INVALID_DISPLAY;
 
+    private int mPowerButtonSuppressionDelayMillis = POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS;
+
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -782,6 +785,9 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.POWER_BUTTON_VERY_LONG_PRESS), false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE), false, this,
+                    UserHandle.USER_ALL);
             updateSettings();
         }
 
@@ -1105,16 +1111,16 @@
                 case SHORT_PRESS_POWER_NOTHING:
                     break;
                 case SHORT_PRESS_POWER_GO_TO_SLEEP:
-                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+                    goToSleepFromPowerButton(eventTime, 0);
                     break;
                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
-                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
-                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+                    goToSleepFromPowerButton(eventTime, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
                     break;
                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
-                    goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
-                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
-                    launchHomeFromHotKey(DEFAULT_DISPLAY);
+                    if (goToSleepFromPowerButton(eventTime,
+                            PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE)) {
+                        launchHomeFromHotKey(DEFAULT_DISPLAY);
+                    }
                     break;
                 case SHORT_PRESS_POWER_GO_HOME:
                     shortPressPowerGoHome();
@@ -1137,6 +1143,35 @@
         }
     }
 
+    /**
+     * Sends the device to sleep as a result of a power button press.
+     *
+     * @return True if the was device was sent to sleep, false if sleep was suppressed.
+     */
+    private boolean goToSleepFromPowerButton(long eventTime, int flags) {
+        // Before we actually go to sleep, we check the last wakeup reason.
+        // If the device very recently woke up from a gesture (like user lifting their device)
+        // then ignore the sleep instruction. This is because users have developed
+        // a tendency to hit the power button immediately when they pick up their device, and we
+        // don't want to put the device back to sleep in those cases.
+        final PowerManager.WakeData lastWakeUp = mPowerManagerInternal.getLastWakeup();
+        if (lastWakeUp != null && lastWakeUp.wakeReason == PowerManager.WAKE_REASON_GESTURE) {
+            final int gestureDelayMillis = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
+                    POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);
+            final long now = SystemClock.uptimeMillis();
+            if (mPowerButtonSuppressionDelayMillis > 0
+                    && (now < lastWakeUp.wakeTime + mPowerButtonSuppressionDelayMillis)) {
+                Slog.i(TAG, "Sleep from power button suppressed. Time since gesture: "
+                        + (now - lastWakeUp.wakeTime) + "ms");
+                return false;
+            }
+        }
+
+        goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, flags);
+        return true;
+    }
+
     private void goToSleep(long eventTime, int reason, int flags) {
         mRequestedOrGoingToSleep = true;
         mPowerManager.goToSleep(eventTime, reason, flags);
@@ -1981,6 +2016,9 @@
             mRingerToggleChord = Settings.Secure.getIntForUser(resolver,
                     Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
                     UserHandle.USER_CURRENT);
+            mPowerButtonSuppressionDelayMillis = Settings.Global.getInt(resolver,
+                    Settings.Global.POWER_BUTTON_SUPPRESSION_DELAY_AFTER_GESTURE_WAKE,
+                    POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS);
             if (!mContext.getResources()
                     .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
                 mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF;
@@ -3594,11 +3632,15 @@
                     }
                 }
             }
-        } else if (ExtconUEventObserver.extconExists()) {
+        } else if (ExtconUEventObserver.extconExists()
+                && ExtconUEventObserver.namedExtconDirExists(HdmiVideoExtconUEventObserver.NAME)) {
             HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();
             plugged = observer.init();
             mHDMIObserver = observer;
+        } else if (localLOGV) {
+            Slog.v(TAG, "Not observing HDMI plug state because HDMI was not found.");
         }
+
         // This dance forces the code in setHdmiPlugged to run.
         // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
         mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
@@ -5658,7 +5700,8 @@
 
     private class HdmiVideoExtconUEventObserver extends ExtconStateObserver<Boolean> {
         private static final String HDMI_EXIST = "HDMI=1";
-        private final ExtconInfo mHdmi = new ExtconInfo("hdmi");
+        private static final String NAME = "hdmi";
+        private final ExtconInfo mHdmi = new ExtconInfo(NAME);
 
         private boolean init() {
             boolean plugged = false;
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 5e829b2..a65a812 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -76,6 +76,12 @@
     private final AtomicBoolean mRequested;
 
     /**
+     * Monotonously increasing ID for the requests sent.
+     */
+    @VisibleForTesting
+    protected int mRequestId;
+
+    /**
      * {@link android.service.attention.AttentionService} API timeout.
      */
     private long mMaxAttentionApiTimeoutMillis;
@@ -105,36 +111,13 @@
     private AtomicLong mConsecutiveTimeoutExtendedCount = new AtomicLong(0);
 
     @VisibleForTesting
-    final AttentionCallbackInternal mCallback = new AttentionCallbackInternal() {
-        @Override
-        public void onSuccess(int result, long timestamp) {
-            Slog.v(TAG, "onSuccess: " + result);
-            if (mRequested.getAndSet(false)) {
-                synchronized (mLock) {
-                    if (mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) {
-                        if (DEBUG) Slog.d(TAG, "Device slept before receiving callback.");
-                        return;
-                    }
-                    if (result == AttentionService.ATTENTION_SUCCESS_PRESENT) {
-                        mOnUserAttention.run();
-                    } else {
-                        resetConsecutiveExtensionCount();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void onFailure(int error) {
-            Slog.i(TAG, "Failed to check attention: " + error);
-            mRequested.set(false);
-        }
-    };
+    AttentionCallbackInternalImpl mCallback;
 
     public AttentionDetector(Runnable onUserAttention, Object lock) {
         mOnUserAttention = onUserAttention;
         mLock = lock;
         mRequested = new AtomicBoolean(false);
+        mRequestId = 0;
 
         // Device starts with an awake state upon boot.
         mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -196,9 +179,7 @@
             return nextScreenDimming;
         } else if (mRequested.get()) {
             if (DEBUG) {
-                // TODO(b/128134941): consider adding a member ID increasing counter in
-                //  AttentionCallbackInternal to track this better.
-                Slog.d(TAG, "Pending attention callback, wait.");
+                Slog.d(TAG, "Pending attention callback with ID=" + mCallback.mId + ", wait.");
             }
             return whenToCheck;
         }
@@ -208,6 +189,8 @@
         // This means that we must assume that the request was successful, and then cancel it
         // afterwards if AttentionManager couldn't deliver it.
         mRequested.set(true);
+        mRequestId++;
+        mCallback = new AttentionCallbackInternalImpl(mRequestId);
         final boolean sent = mAttentionManager.checkAttention(getAttentionTimeout(), mCallback);
         if (!sent) {
             mRequested.set(false);
@@ -301,4 +284,40 @@
         pw.print(" mAttentionServiceSupported=" + isAttentionServiceSupported());
         pw.print(" mRequested=" + mRequested);
     }
+
+    @VisibleForTesting
+    final class AttentionCallbackInternalImpl extends AttentionCallbackInternal {
+        private final int mId;
+
+        AttentionCallbackInternalImpl(int id) {
+            this.mId = id;
+        }
+
+        @Override
+        public void onSuccess(int result, long timestamp) {
+            Slog.v(TAG, "onSuccess: " + result + ", ID: " + mId);
+            // If we don't check for request ID it's possible to get into a loop: success leads
+            // to the onUserAttention(), which in turn triggers updateUserActivity(), which will
+            // call back onSuccess() instantaneously if there is a cached value, and circle repeats.
+            if (mId == mRequestId && mRequested.getAndSet(false)) {
+                synchronized (mLock) {
+                    if (mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE) {
+                        if (DEBUG) Slog.d(TAG, "Device slept before receiving callback.");
+                        return;
+                    }
+                    if (result == AttentionService.ATTENTION_SUCCESS_PRESENT) {
+                        mOnUserAttention.run();
+                    } else {
+                        resetConsecutiveExtensionCount();
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onFailure(int error) {
+            Slog.i(TAG, "Failed to check attention: " + error + ", ID: " + mId);
+            mRequested.set(false);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfe11bf..e2bbb2d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -52,6 +52,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.PowerManager.ServiceType;
+import android.os.PowerManager.WakeData;
 import android.os.PowerManager.WakeReason;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
@@ -4850,6 +4851,12 @@
         }
     }
 
+    private PowerManager.WakeData getLastWakeupInternal() {
+        synchronized (mLock) {
+            return new WakeData(mLastWakeTime, mLastWakeReason);
+        }
+    }
+
     private final class LocalService extends PowerManagerInternal {
         @Override
         public void setScreenBrightnessOverrideFromWindowManager(int screenBrightness) {
@@ -4971,5 +4978,10 @@
         public boolean wasDeviceIdleFor(long ms) {
             return wasDeviceIdleForInternal(ms);
         }
+
+        @Override
+        public WakeData getLastWakeup() {
+            return getLastWakeupInternal();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 654c477..0e20905 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -39,7 +39,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.Signature;
 import android.database.CursorWindow;
-import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -201,8 +200,7 @@
                     // Package is being upgraded - we're about to get ACTION_PACKAGE_ADDED
                     return;
                 }
-                AsyncTask.THREAD_POOL_EXECUTOR.execute(
-                        () -> performInitialGrantsIfNecessaryAsync(userId));
+                performInitialGrantsIfNecessaryAsync(userId);
             }
         }, UserHandle.ALL, intentFilter, null, null);
     }
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 27f3387..1edb93a 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -455,8 +455,7 @@
         // Add in all the apps for every user/profile.
         for (UserInfo profile : users) {
             List<PackageInfo> pi =
-                    pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES
-                            | PackageManager.MATCH_APEX, profile.id);
+                    pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
             for (int j = 0; j < pi.size(); j++) {
                 if (pi.get(j).applicationInfo != null) {
                     String installer;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 9cbf00b..af009ec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1314,6 +1314,17 @@
     }
 
     @Override
+    public void onNotificationBubbleChanged(String key, boolean isBubble) {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onNotificationBubbleChanged(key, isBubble);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         (new StatusBarShellCommand(this, mContext)).exec(
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 10afbef..0891ba4 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -99,7 +99,7 @@
  * data for Tron, logcat, event logs and {@link android.app.WaitResult}.
  *
  * Tests:
- * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
+ * atest CtsWindowManagerDeviceTestCases:ActivityMetricsLoggerTests
  */
 class ActivityMetricsLogger {
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ee6cf54..0820b0d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3372,6 +3372,11 @@
 
                 if (stack.inFreeformWindowingMode()) {
                     stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+                } else if (stack.getParent().inFreeformWindowingMode()) {
+                    // If the window is on a freeform display, set it to undefined. It will be
+                    // resolved to freeform and it can adjust windowing mode when the display mode
+                    // changes in runtime.
+                    stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
                 } else {
                     stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
                 }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a57dd6d..43d9e43 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -268,6 +268,9 @@
     private int[] mNavigationBarHeightForRotationInCarMode = new int[4];
     private int[] mNavigationBarWidthForRotationInCarMode = new int[4];
 
+    /** See {@link #getNavigationBarFrameHeight} */
+    private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
+
     /** Cached value of {@link ScreenShapeHelper#getWindowOutsetBottomPx} */
     @Px private int mWindowOutsetBottom;
 
@@ -286,10 +289,6 @@
                 }
             };
 
-    // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
-    private NavigationBarExperiments mExperiments = new NavigationBarExperiments();
-    // EXPERIMENT END
-
     @GuardedBy("mHandler")
     private SleepToken mDreamingSleepToken;
 
@@ -1621,11 +1620,9 @@
             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
             final int top = cutoutSafeUnrestricted.bottom
                     - getNavigationBarHeight(rotation, uiMode);
-            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
             final int topNavBar = cutoutSafeUnrestricted.bottom
-                    - mExperiments.getNavigationBarFrameHeight();
+                    - getNavigationBarFrameHeight(rotation, uiMode);
             navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
-            // EXPERIMENT END
             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -1648,11 +1645,7 @@
             // Landscape screen; nav bar goes to the right.
             final int left = cutoutSafeUnrestricted.right
                     - getNavigationBarWidth(rotation, uiMode);
-            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
-            final int leftNavBar = cutoutSafeUnrestricted.right
-                    - mExperiments.getNavigationBarFrameWidth();
-            navigationFrame.set(leftNavBar, 0, displayFrames.mUnrestricted.right, displayHeight);
-            // EXPERIMENT END
+            navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -1675,11 +1668,7 @@
             // Seascape screen; nav bar goes to the left.
             final int right = cutoutSafeUnrestricted.left
                     + getNavigationBarWidth(rotation, uiMode);
-            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
-            final int rightNavBar = cutoutSafeUnrestricted.left
-                    + mExperiments.getNavigationBarFrameWidth();
-            navigationFrame.set(displayFrames.mUnrestricted.left, 0, rightNavBar, displayHeight);
-            // EXPERIMENT END
+            navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -1887,10 +1876,21 @@
                 }
             }
 
-            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
-            // Offset the ime to avoid overlapping with the nav bar
-            mExperiments.offsetWindowFramesForNavBar(mNavigationBarPosition, win);
-            // EXPERIMENT END
+            // In case the navigation bar is on the bottom, we use the frame height instead of the
+            // regular height for the insets we send to the IME as we need some space to show
+            // additional buttons in SystemUI when the IME is up.
+            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
+                final int rotation = displayFrames.mRotation;
+                final int uimode = mService.mPolicy.getUiMode();
+                final int navHeightOffset = getNavigationBarFrameHeight(rotation, uimode)
+                        - getNavigationBarHeight(rotation, uimode);
+                if (navHeightOffset > 0) {
+                    cf.bottom -= navHeightOffset;
+                    sf.bottom -= navHeightOffset;
+                    vf.bottom -= navHeightOffset;
+                    dcf.bottom -= navHeightOffset;
+                }
+            }
 
             // IM dock windows always go to the bottom of the screen.
             attrs.gravity = Gravity.BOTTOM;
@@ -2623,6 +2623,7 @@
         final int upsideDownRotation = displayRotation.getUpsideDownRotation();
         final int landscapeRotation = displayRotation.getLandscapeRotation();
         final int seascapeRotation = displayRotation.getSeascapeRotation();
+        final int uiMode = mService.mPolicy.getUiMode();
 
         if (hasStatusBar()) {
             mStatusBarHeightForRotation[portraitRotation] =
@@ -2646,6 +2647,14 @@
         mNavigationBarHeightForRotationDefault[seascapeRotation] =
                 res.getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
 
+        // Height of the navigation bar frame when presented horizontally at bottom
+        mNavigationBarFrameHeightForRotationDefault[portraitRotation] =
+        mNavigationBarFrameHeightForRotationDefault[upsideDownRotation] =
+                res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
+        mNavigationBarFrameHeightForRotationDefault[landscapeRotation] =
+        mNavigationBarFrameHeightForRotationDefault[seascapeRotation] =
+                res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height_landscape);
+
         // Width of the navigation bar when presented vertically along one side
         mNavigationBarWidthForRotationDefault[portraitRotation] =
         mNavigationBarWidthForRotationDefault[upsideDownRotation] =
@@ -2674,16 +2683,10 @@
         mSideGestureInset = res.getDimensionPixelSize(R.dimen.config_backGestureInset);
         mNavigationBarLetsThroughTaps = res.getBoolean(R.bool.config_navBarTapThrough);
 
-        // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
-        mExperiments.onConfigurationChanged(uiContext);
-        // EXPERIMENT END
-
-        // EXPERIMENT: TODO(b/113952590): Replace with real code after experiment.
-        // This should calculate how much above the frame we accept gestures. Currently,
-        // we extend the frame to capture the gestures, so this is 0.
-        mBottomGestureAdditionalInset = mExperiments.getNavigationBarFrameHeight()
-                - mExperiments.getNavigationBarFrameHeight();
-        // EXPERIMENT END
+        // This should calculate how much above the frame we accept gestures.
+        mBottomGestureAdditionalInset = Math.max(0,
+                res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
+                        - getNavigationBarFrameHeight(portraitRotation, uiMode));
 
         updateConfigurationAndScreenSizeDependentBehaviors();
         mWindowOutsetBottom = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
@@ -2749,6 +2752,26 @@
     }
 
     /**
+     * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that
+     * is used for spacing to show additional buttons on the navigation bar (such as the ime
+     * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible
+     * height that we send to the app as content insets that can be smaller.
+     * <p>
+     * In car mode it will return the same height as {@link #getNavigationBarHeight}
+     *
+     * @param rotation specifies rotation to return dimension from
+     * @param uiMode to determine if in car mode
+     * @return navigation bar frame height
+     */
+    private int getNavigationBarFrameHeight(int rotation, int uiMode) {
+        if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) {
+            return mNavigationBarHeightForRotationInCarMode[rotation];
+        } else {
+            return mNavigationBarFrameHeightForRotationDefault[rotation];
+        }
+    }
+
+    /**
      * Return the display height available after excluding any screen
      * decorations that could never be removed in Honeycomb. That is, system bar or
      * button bar.
diff --git a/services/core/java/com/android/server/wm/NavigationBarExperiments.java b/services/core/java/com/android/server/wm/NavigationBarExperiments.java
deleted file mode 100644
index bb3ff5e..0000000
--- a/services/core/java/com/android/server/wm/NavigationBarExperiments.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
-
-import android.content.Context;
-import android.graphics.Rect;
-
-/**
- * This class acts as a proxy for Navigation Bar experiments enabled with custom overlays
- * {@see OverlayManagerService}. By default with no overlays, this class will essentially do nothing
- * and pass the original resource data back. By default the navigation bar height/width is the same
- * as the frame height/width and therefore any offsets calculated will cancel out and do nothing.
- * TODO(b/113952590): Remove class once experiment in bug is completed
- */
-public class NavigationBarExperiments {
-
-    private int mNavigationBarHeight;
-    private int mNavigationBarWidth;
-
-    /**
-     * This represents the height of the navigation bar buttons. With no experiments or overlays
-     * enabled, the frame height is the same as the normal navigation bar height.
-     */
-    private int mNavigationBarFrameHeight;
-
-    /**
-     * This represents the width of the navigation bar buttons. With no experiments or overlays
-     * enabled, the frame width is the same as the normal navigation bar width.
-     */
-    private int mNavigationBarFrameWidth;
-
-    /**
-     * Call when configuration change to refresh resource dimensions
-     * @param systemUiContext to get the resource values
-     */
-    public void onConfigurationChanged(Context systemUiContext) {
-        // Cache all the values again
-        mNavigationBarHeight = systemUiContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_height);
-        mNavigationBarWidth = systemUiContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_width);
-        mNavigationBarFrameHeight = systemUiContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_frame_height);
-        mNavigationBarFrameWidth = systemUiContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.navigation_bar_frame_width);
-    }
-
-    public int getNavigationBarHeight() {
-        return mNavigationBarHeight;
-    }
-
-    public int getNavigationBarWidth() {
-        return mNavigationBarWidth;
-    }
-
-    public int getNavigationBarFrameHeight() {
-        return mNavigationBarFrameHeight;
-    }
-
-    public int getNavigationBarFrameWidth() {
-        return mNavigationBarFrameWidth;
-    }
-
-    /**
-     * If navigation frame width/height is different than navigation bar width/height then only
-     * offset the ime's and home activity's window rects depending on the navigation bar position to
-     * add a gap where the navigation bar would have been drawn. With no experiments or overlays
-     * enabled, the height/width is the same as the frame height/width and the offsets calculated
-     * will be 0 and this function will do nothing.
-     * @param navPosition position of navigation bar (left, right or bottom)
-     * @param w the window that is being offset by experiment
-     */
-    public void offsetWindowFramesForNavBar(int navPosition, WindowState w) {
-        if (w.getAttrs().type != TYPE_INPUT_METHOD) {
-            return;
-        }
-
-        final WindowFrames windowFrames = w.getWindowFrames();
-        final Rect cf = windowFrames.mContentFrame;
-        switch (navPosition) {
-            case NAV_BAR_BOTTOM:
-                int navHeight = getNavigationBarFrameHeight() - getNavigationBarHeight();
-                if (navHeight > 0) {
-                    cf.bottom -= navHeight;
-                    windowFrames.mStableFrame.bottom -= navHeight;
-                }
-                break;
-            case NAV_BAR_LEFT:
-            case NAV_BAR_RIGHT:
-                int navWidth = getNavigationBarFrameWidth() - getNavigationBarWidth();
-                if (navWidth > 0) {
-                    if (navPosition == NAV_BAR_LEFT) {
-                        cf.left += navWidth;
-                    } else {
-                        cf.right -= navWidth;
-                    }
-                }
-                break;
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 904c503..14585c5 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -274,7 +274,7 @@
                 }
                 // Even though we want to keep original bounds, we still don't want it to stomp on
                 // an existing task.
-                adjustBoundsToAvoidConflict(display, outParams.mBounds);
+                adjustBoundsToAvoidConflictInDisplay(display, outParams.mBounds);
             }
         } else {
             if (source != null && source.inFreeformWindowingMode()
@@ -534,7 +534,7 @@
         }
 
         // Lastly we adjust bounds to avoid conflicts with other tasks as much as possible.
-        adjustBoundsToAvoidConflict(display, inOutBounds);
+        adjustBoundsToAvoidConflictInDisplay(display, inOutBounds);
     }
 
     private int convertOrientationToScreenOrientation(int orientation) {
@@ -678,16 +678,9 @@
      * @param display the display which tasks are to check
      * @param inOutBounds the bounds used to input initial bounds and output result bounds
      */
-    private void adjustBoundsToAvoidConflict(@NonNull ActivityDisplay display,
+    private void adjustBoundsToAvoidConflictInDisplay(@NonNull ActivityDisplay display,
             @NonNull Rect inOutBounds) {
-        final Rect displayBounds = display.getBounds();
-        if (!displayBounds.contains(inOutBounds)) {
-            // The initial bounds are already out of display. The scanning algorithm below doesn't
-            // work so well with them.
-            return;
-        }
-
-        final List<TaskRecord> tasksToCheck = new ArrayList<>();
+        final List<Rect> taskBoundsToCheck = new ArrayList<>();
         for (int i = 0; i < display.getChildCount(); ++i) {
             final ActivityStack stack = display.getChildAt(i);
             if (!stack.inFreeformWindowingMode()) {
@@ -695,11 +688,35 @@
             }
 
             for (int j = 0; j < stack.getChildCount(); ++j) {
-                tasksToCheck.add(stack.getChildAt(j));
+                taskBoundsToCheck.add(stack.getChildAt(j).getBounds());
             }
         }
+        adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds);
+    }
 
-        if (!boundsConflict(tasksToCheck, inOutBounds)) {
+    /**
+     * Adjusts input bounds to avoid conflict with provided display bounds and list of tasks bounds
+     * for the display.
+     *
+     * Scans the bounds in directions to find a candidate location that does not conflict with the
+     * provided list of task bounds. If starting bounds are outside the display bounds or if no
+     * suitable candidate bounds are found, the method returns the input bounds.
+     *
+     * @param displayBounds display bounds used to restrict the candidate bounds
+     * @param taskBoundsToCheck list of task bounds to check for conflict
+     * @param inOutBounds the bounds used to input initial bounds and output result bounds
+     */
+    @VisibleForTesting
+    void adjustBoundsToAvoidConflict(@NonNull Rect displayBounds,
+            @NonNull List<Rect> taskBoundsToCheck,
+            @NonNull Rect inOutBounds) {
+        if (!displayBounds.contains(inOutBounds)) {
+            // The initial bounds are already out of display. The scanning algorithm below doesn't
+            // work so well with them.
+            return;
+        }
+
+        if (!boundsConflict(taskBoundsToCheck, inOutBounds)) {
             // Current proposal doesn't conflict with any task. Early return to avoid unnecessary
             // calculation.
             return;
@@ -713,11 +730,13 @@
             }
 
             mTmpBounds.set(inOutBounds);
-            while (boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+            while (boundsConflict(taskBoundsToCheck, mTmpBounds)
+                    && displayBounds.contains(mTmpBounds)) {
                 shiftBounds(direction, displayBounds, mTmpBounds);
             }
 
-            if (!boundsConflict(tasksToCheck, mTmpBounds) && displayBounds.contains(mTmpBounds)) {
+            if (!boundsConflict(taskBoundsToCheck, mTmpBounds)
+                    && displayBounds.contains(mTmpBounds)) {
                 // Found a candidate. Just use this.
                 inOutBounds.set(mTmpBounds);
                 if (DEBUG) appendLog("avoid-bounds-conflict=" + inOutBounds);
@@ -772,16 +791,16 @@
         mTmpDirections[1] = Gravity.TOP | Gravity.LEFT;
     }
 
-    private boolean boundsConflict(@NonNull List<TaskRecord> tasks, @NonNull Rect bounds) {
-        for (TaskRecord task : tasks) {
-            final Rect taskBounds = task.getBounds();
-            final boolean leftClose = Math.abs(taskBounds.left - bounds.left)
+    private boolean boundsConflict(@NonNull List<Rect> taskBoundsToCheck,
+                                   @NonNull Rect candidateBounds) {
+        for (Rect taskBounds : taskBoundsToCheck) {
+            final boolean leftClose = Math.abs(taskBounds.left - candidateBounds.left)
                     < BOUNDS_CONFLICT_THRESHOLD;
-            final boolean topClose = Math.abs(taskBounds.top - bounds.top)
+            final boolean topClose = Math.abs(taskBounds.top - candidateBounds.top)
                     < BOUNDS_CONFLICT_THRESHOLD;
-            final boolean rightClose = Math.abs(taskBounds.right - bounds.right)
+            final boolean rightClose = Math.abs(taskBounds.right - candidateBounds.right)
                     < BOUNDS_CONFLICT_THRESHOLD;
-            final boolean bottomClose = Math.abs(taskBounds.bottom - bounds.bottom)
+            final boolean bottomClose = Math.abs(taskBounds.bottom - candidateBounds.bottom)
                     < BOUNDS_CONFLICT_THRESHOLD;
 
             if ((leftClose && topClose) || (leftClose && bottomClose) || (rightClose && topClose)
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index eb919eb..12b62b9 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -23,6 +23,7 @@
 import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -98,7 +99,7 @@
     private final ActivityTaskManagerService mAtm;
     // The actual proc...  may be null only if 'persistent' is true (in which case we are in the
     // process of launching the app)
-    private volatile IApplicationThread mThread;
+    private IApplicationThread mThread;
     // Currently desired scheduling class
     private volatile int mCurSchedGroup;
     // Currently computed process state
@@ -192,8 +193,11 @@
         return mPid;
     }
 
+    @HotPath(caller = HotPath.PROCESS_CHANGE)
     public void setThread(IApplicationThread thread) {
-        mThread = thread;
+        synchronized (mAtm.mGlobalLockWithoutBoost) {
+            mThread = thread;
+        }
     }
 
     IApplicationThread getThread() {
@@ -507,7 +511,14 @@
                 continue;
             }
             ActivityRecord topActivity = task.getTopActivity();
-            if (topActivity != null && topActivity.visible) {
+            if (topActivity == null) {
+                continue;
+            }
+            // If an activity has just been started it will not yet be visible, but
+            // is expected to be soon. We treat this as if it were already visible.
+            // This ensures a subsequent activity can be started even before this one
+            // becomes visible.
+            if (topActivity.visible || topActivity.isState(INITIALIZING)) {
                 return true;
             }
         }
diff --git a/services/net/Android.bp b/services/net/Android.bp
index f73a285..d72f1cf 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,8 +3,6 @@
     name: "ipmemorystore-aidl-interfaces",
     local_include_dir: "java",
     srcs: [
-        // TODO: Define and use a filegroup for these files, since they're also used in
-        // networkstack-aidl-interfaces. This does not appear to work at the moment.
         "java/android/net/IIpMemoryStore.aidl",
         "java/android/net/IIpMemoryStoreCallbacks.aidl",
         "java/android/net/ipmemorystore/**/*.aidl",
@@ -17,17 +15,16 @@
             enabled: false,
         },
     },
-    api_dir: "aidl/networkstack",
+    api_dir: "aidl/ipmemorystore",
+    versions: ["1"],
 }
 
 aidl_interface {
     name: "networkstack-aidl-interfaces",
     local_include_dir: "java",
-    include_dirs: ["frameworks/base/core/java"],  // For framework parcelables.
+    include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
     srcs: [
         "java/android/net/DhcpResultsParcelable.aidl",
-        "java/android/net/IIpMemoryStore.aidl",
-        "java/android/net/IIpMemoryStoreCallbacks.aidl",
         "java/android/net/INetworkMonitor.aidl",
         "java/android/net/INetworkMonitorCallbacks.aidl",
         "java/android/net/INetworkStackConnector.aidl",
@@ -41,7 +38,6 @@
         "java/android/net/dhcp/IDhcpServerCallbacks.aidl",
         "java/android/net/ip/IIpClient.aidl",
         "java/android/net/ip/IIpClientCallbacks.aidl",
-        "java/android/net/ipmemorystore/**/*.aidl",
     ],
     backend: {
         ndk: {
@@ -52,6 +48,8 @@
         },
     },
     api_dir: "aidl/networkstack",
+    imports: ["ipmemorystore-aidl-interfaces"],
+    versions: ["1"],
 }
 
 java_library_static {
@@ -62,7 +60,7 @@
         "ipmemorystore-client",
         "netd_aidl_interface-java",
         "networkstack-aidl-interfaces-java",
-    ]
+    ],
 }
 
 java_library_static {
@@ -75,7 +73,7 @@
     ],
     static_libs: [
         "ipmemorystore-aidl-interfaces-java",
-    ]
+    ],
 }
 
 filegroup {
diff --git a/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..a8cbab2
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+  oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+  oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+  oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+  oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+  oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+  oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+  oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+  byte[] data;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+  oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+  oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+  oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+  oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+  oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+  byte[] assignedV4Address;
+  long assignedV4AddressExpiry;
+  String groupHint;
+  android.net.ipmemorystore.Blob[] dnsAddresses;
+  int mtu;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+  String l2Key1;
+  String l2Key2;
+  float confidence;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+  int resultCode;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..92b5345
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+  android.net.StaticIpConfiguration baseConfiguration;
+  int leaseDuration;
+  int mtu;
+  String serverAddress;
+  String vendorInfo;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..b19f522
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl
@@ -0,0 +1,17 @@
+package android.net;
+interface INetworkMonitor {
+  oneway void start();
+  oneway void launchCaptivePortalApp();
+  oneway void notifyCaptivePortalAppFinished(int response);
+  oneway void setAcceptPartialConnectivity();
+  oneway void forceReevaluation(int uid);
+  oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+  oneway void notifyDnsResponse(int returnCode);
+  oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+  oneway void notifyNetworkDisconnected();
+  oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+  oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+  const int NETWORK_TEST_RESULT_VALID = 0;
+  const int NETWORK_TEST_RESULT_INVALID = 1;
+  const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+  oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+  oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+  oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+  oneway void showProvisioningNotification(String action, String packageName);
+  oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+  oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+  oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+  oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+  oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+  oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+  android.net.LinkAddress[] ipAddresses;
+  android.net.IpPrefix[] directlyConnectedRoutes;
+  String[] dnsServers;
+  String gateway;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+  String hostname;
+  String[] ips;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+  boolean enableIPv4;
+  boolean enableIPv6;
+  boolean usingMultinetworkPolicyTracker;
+  boolean usingIpReachabilityMonitor;
+  int requestedPreDhcpActionMs;
+  android.net.InitialConfigurationParcelable initialConfig;
+  android.net.StaticIpConfiguration staticIpConfig;
+  android.net.apf.ApfCapabilities apfCapabilities;
+  int provisioningTimeoutMs;
+  int ipv6AddrGenMode;
+  android.net.Network network;
+  String displayName;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+  byte[] srcAddress;
+  int srcPort;
+  byte[] dstAddress;
+  int dstPort;
+  int seq;
+  int ack;
+  int rcvWnd;
+  int rcvWndScale;
+  int tos;
+  int ttl;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+  int serverAddr;
+  int serverAddrPrefixLength;
+  int[] defaultRouters;
+  int[] dnsServers;
+  int[] excludedAddrs;
+  long dhcpLeaseTimeSecs;
+  int linkMtu;
+  boolean metered;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+  oneway void start(in android.net.INetworkStackStatusCallback cb);
+  oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+  oneway void stop(in android.net.INetworkStackStatusCallback cb);
+  const int STATUS_UNKNOWN = 0;
+  const int STATUS_SUCCESS = 1;
+  const int STATUS_INVALID_ARGUMENT = 2;
+  const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+  oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..95a1574
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl
@@ -0,0 +1,14 @@
+package android.net.ip;
+interface IIpClient {
+  oneway void completedPreDhcpAction();
+  oneway void confirmConfiguration();
+  oneway void readPacketFilterComplete(in byte[] data);
+  oneway void shutdown();
+  oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+  oneway void stop();
+  oneway void setTcpBufferSizes(in String tcpBufferSizes);
+  oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+  oneway void setMulticastFilter(boolean enabled);
+  oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+  oneway void removeKeepalivePacketFilter(int slot);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+  oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+  oneway void onPreDhcpAction();
+  oneway void onPostDhcpAction();
+  oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+  oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+  oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+  oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+  oneway void onReachabilityLost(in String logMsg);
+  oneway void onQuit();
+  oneway void installPacketFilter(in byte[] filter);
+  oneway void startReadPacketFilter();
+  oneway void setFallbackMulticastFilter(boolean enabled);
+  oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 9248299..4a115e6 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -41,6 +41,11 @@
                     public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) {
                         mService.complete(memoryStore);
                     }
+
+                    @Override
+                    public int getInterfaceVersion() {
+                        return this.VERSION;
+                    }
                 });
     }
 
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 90624e0..714ade1 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -175,6 +175,11 @@
         public void setNeighborDiscoveryOffload(boolean enable) {
             mCb.setNeighborDiscoveryOffload(enable);
         }
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 
     /**
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index fc1128b..66884c6 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -277,6 +277,11 @@
         }
 
         public abstract void callback(int statusCode);
+
+        @Override
+        public int getInterfaceVersion() {
+            return this.VERSION;
+        }
     }
 
     private class DhcpServerCallbacksImpl extends DhcpServerCallbacks {
diff --git a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
index 22978a2..a17483a 100644
--- a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
@@ -40,6 +40,11 @@
                     listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob);
                 }
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 }
diff --git a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
index 9e7c1c8..e608aec 100644
--- a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
@@ -40,6 +40,11 @@
                     listener.onL2KeyResponse(new Status(statusParcelable), l2Key);
                 }
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 }
diff --git a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
index 59da268..ca6f302 100644
--- a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
@@ -44,6 +44,11 @@
                             new NetworkAttributes(networkAttributesParcelable));
                 }
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 }
diff --git a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
index 0154fd2..67f8da8 100644
--- a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
@@ -43,6 +43,11 @@
                             new SameL3NetworkResponse(sameL3NetworkResponseParcelable));
                 }
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 }
diff --git a/services/net/java/android/net/ipmemorystore/OnStatusListener.java b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
index 824b7b0..4262efd 100644
--- a/services/net/java/android/net/ipmemorystore/OnStatusListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
@@ -39,6 +39,11 @@
                     listener.onComplete(new Status(statusParcelable));
                 }
             }
+
+            @Override
+            public int getInterfaceVersion() {
+                return this.VERSION;
+            }
         };
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index 3f9a57e..3cdadd5 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -19,7 +19,6 @@
 import static android.content.om.OverlayInfo.STATE_DISABLED;
 import static android.content.om.OverlayInfo.STATE_ENABLED;
 import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
-import static android.content.om.OverlayInfo.STATE_TARGET_IS_BEING_REPLACED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -172,8 +171,9 @@
         mImpl.setEnabled(OVERLAY, true, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
 
+        // target upgrades do not change the state of the overlay
         beginUpgradeTargetPackage(TARGET, USER);
-        assertState(STATE_TARGET_IS_BEING_REPLACED, OVERLAY, USER);
+        assertState(STATE_ENABLED, OVERLAY, USER);
 
         endUpgradeTargetPackage(TARGET, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index 4de00f7..c30a7dd 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -22,6 +22,8 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -216,6 +218,53 @@
     }
 
     @Test
+    public void testCallbackOnSuccess_doesNotCallNonCurrentCallback() {
+        mAttentionDetector.mRequestId = 5;
+        registerAttention(); // mRequestId = 6;
+        mAttentionDetector.mRequestId = 55;
+
+        mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
+                SystemClock.uptimeMillis());
+        verify(mOnUserAttention, never()).run();
+    }
+
+    @Test
+    public void testCallbackOnSuccess_callsCallbackAfterOldCallbackCame() {
+        mAttentionDetector.mRequestId = 5;
+        registerAttention(); // mRequestId = 6;
+        mAttentionDetector.mRequestId = 55;
+
+        mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
+                SystemClock.uptimeMillis()); // old callback came
+        mAttentionDetector.mRequestId = 6; // now back to current
+        mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
+                SystemClock.uptimeMillis());
+        verify(mOnUserAttention).run();
+    }
+
+    @Test
+    public void testCallbackOnSuccess_DoesNotGoIntoInfiniteLoop() {
+        // Mimic real behavior
+        doAnswer((invocation) -> {
+            // Mimic a cache hit: calling onSuccess() immediately
+            registerAttention();
+            mAttentionDetector.mRequestId++;
+            mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
+                    SystemClock.uptimeMillis());
+            return null;
+        }).when(mOnUserAttention).run();
+
+        registerAttention();
+        // This test fails with literal stack overflow:
+        // e.g. java.lang.StackOverflowError: stack size 1039KB
+        mAttentionDetector.mCallback.onSuccess(AttentionService.ATTENTION_SUCCESS_PRESENT,
+                SystemClock.uptimeMillis());
+
+        // We don't actually get here when the test fails
+        verify(mOnUserAttention, atMost(1)).run();
+    }
+
+    @Test
     public void testCallbackOnFailure_unregistersCurrentRequestCode() {
         registerAttention();
         mAttentionDetector.mCallback.onFailure(AttentionService.ATTENTION_FAILURE_UNKNOWN);
@@ -232,7 +281,6 @@
     }
 
     private class TestableAttentionDetector extends AttentionDetector {
-
         private boolean mAttentionServiceSupported;
 
         TestableAttentionDetector() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 2d101dd..34bb0a8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -71,7 +71,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
@@ -5047,4 +5046,112 @@
         mBinderService.areBubblesAllowedForPackage(mContext.getPackageName(),
                 mUid + UserHandle.PER_USER_RANGE);
     }
+
+    @Test
+    public void testNotificationBubbleChanged_false() throws Exception {
+        // Bubbles are allowed!
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+        when(mPreferencesHelper.getNotificationChannel(
+                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+                mTestNotificationChannel);
+        when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+                mTestNotificationChannel.getImportance());
+
+        // Notif with bubble metadata but not our other misc requirements
+        NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+                null /* tvExtender */, true /* isBubble */);
+
+        // Say we're foreground
+        when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
+                IMPORTANCE_FOREGROUND);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // First we were a bubble
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+        assertTrue((notifsBefore[0].getNotification().flags & FLAG_BUBBLE) != 0);
+
+        // Notify we're not a bubble
+        mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
+        waitForIdle();
+
+        // Now we are not a bubble
+        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsAfter.length);
+        assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
+    }
+
+    @Test
+    public void testNotificationBubbleChanged_true() throws Exception {
+        // Bubbles are allowed!
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+        when(mPreferencesHelper.getNotificationChannel(
+                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+                mTestNotificationChannel);
+        when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+                mTestNotificationChannel.getImportance());
+
+        // Plain notification that has bubble metadata
+        NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+                null /* tvExtender */, true /* isBubble */);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // Would be a normal notification because wouldn't have met requirements to bubble
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+        assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
+
+        // Make the package foreground so that we're allowed to be a bubble
+        when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
+                IMPORTANCE_FOREGROUND);
+
+        // Notify we are now a bubble
+        mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
+        waitForIdle();
+
+        // Make sure we are a bubble
+        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsAfter.length);
+        assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
+    }
+
+    @Test
+    public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
+        // Bubbles are allowed!
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
+        when(mPreferencesHelper.getNotificationChannel(
+                anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+                mTestNotificationChannel);
+        when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+                mTestNotificationChannel.getImportance());
+
+        // Notif that is not a bubble
+        NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+                null /* tvExtender */, true /* isBubble */);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // Would be a normal notification because wouldn't have met requirements to bubble
+        StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsBefore.length);
+        assertEquals((notifsBefore[0].getNotification().flags & FLAG_BUBBLE), 0);
+
+        // Notify we are now a bubble
+        mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
+        waitForIdle();
+
+        // We still wouldn't be a bubble because the notification didn't meet requirements
+        StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
+        assertEquals(1, notifsAfter.length);
+        assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index cdbb121..f918149 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -52,6 +52,8 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 /**
@@ -1206,6 +1208,23 @@
         assertEquals(new Rect(120, 0, 320, 100), mResult.mBounds);
     }
 
+    @Test
+    public void testAdjustBoundsToAvoidConflictAlwaysExits() {
+        Rect displayBounds = new Rect(0, 0, 40, 40);
+        List<Rect> existingTaskBounds = new ArrayList<>();
+        for (int i = 0; i < 9; i++) {
+            for (int j = 0; j < 9; j++) {
+                int left = i * 5;
+                int top = j * 5;
+                existingTaskBounds.add(new Rect(left, top, left + 20, top + 20));
+            }
+        }
+        Rect startingBounds = new Rect(0, 0, 20, 20);
+        Rect adjustedBounds = new Rect(startingBounds);
+        mTarget.adjustBoundsToAvoidConflict(displayBounds, existingTaskBounds, adjustedBounds);
+        assertEquals(startingBounds, adjustedBounds);
+    }
+
     private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
         final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
         display.setWindowingMode(windowingMode);
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 2272dc9..8336d1b 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -58,15 +58,15 @@
     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mSignalStrength; // To be removed
     private int mRssi;
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mRsrp;
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mRsrq;
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mRssnr;
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mCqi;
-    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+    @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
     private int mTimingAdvance;
     private int mLevel;
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d4f9874..32105ad 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2064,7 +2064,6 @@
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
             intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
-            intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
         }
     }
 
@@ -2075,9 +2074,6 @@
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
-        //FIXME this is using phoneId and slotIndex interchangeably
-        //Eventually, this should be removed as it is not the slot id
-        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
     }
 
     /**
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index fa6cfcb..22f078f 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -635,7 +635,7 @@
                 != second.getEmergencyServiceCategoryBitmask()) {
             return false;
         }
-        if (first.getEmergencyUrns().equals(second.getEmergencyUrns())) {
+        if (!first.getEmergencyUrns().equals(second.getEmergencyUrns())) {
             return false;
         }
         if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) {
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index d41a5d6..f9304f2 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -39,6 +39,7 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -774,6 +775,40 @@
         }
     }
 
+    @Test
+    @Ignore("b/120200473")
+    /**
+     * Test rollback when app is updated to its same version.
+     */
+    public void testSameVersionUpdate() throws Exception {
+        try {
+            RollbackTestUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
+            RollbackManager rm = RollbackTestUtils.getRollbackManager();
+
+            RollbackTestUtils.uninstall(TEST_APP_A);
+            RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+            RollbackTestUtils.install("RollbackTestAppAv2.apk", true);
+            RollbackTestUtils.install("RollbackTestAppACrashingV2.apk", true);
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+                    rm.getAvailableRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback);
+
+            RollbackTestUtils.rollback(rollback.getRollbackId());
+            assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+            rollback = getUniqueRollbackInfoForPackage(
+                    rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
+            assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback);
+        } finally {
+            RollbackTestUtils.dropShellPermissionIdentity();
+        }
+    }
+
     /**
      * Test bad update automatic rollback.
      */
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 44380cc..5f08a34 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -131,6 +131,7 @@
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.ProxyInfo;
+import android.net.ResolverParamsParcel;
 import android.net.RouteInfo;
 import android.net.SocketKeepalive;
 import android.net.UidRange;
@@ -262,7 +263,8 @@
     @Mock INetd mMockNetd;
     @Mock NetworkStackClient mNetworkStack;
 
-    private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
+    private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
+            ArgumentCaptor.forClass(ResolverParamsParcel.class);
 
     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
@@ -4819,16 +4821,13 @@
     @Test
     public void testBasicDnsConfigurationPushed() throws Exception {
         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
-        ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
 
         // Clear any interactions that occur as a result of CS starting up.
         reset(mMockDnsResolver);
 
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         waitForIdle();
-        verify(mMockDnsResolver, never()).setResolverConfiguration(
-                anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
-                eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
+        verify(mMockDnsResolver, never()).setResolverConfiguration(any());
         verifyNoMoreInteractions(mMockDnsResolver);
 
         final LinkProperties cellLp = new LinkProperties();
@@ -4846,35 +4845,33 @@
         mCellNetworkAgent.connect(false);
         waitForIdle();
         // CS tells netd about the empty DNS config for this network.
-        verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
-                eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
+        verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
         reset(mMockDnsResolver);
 
         cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
         mCellNetworkAgent.sendLinkProperties(cellLp);
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
-        assertEquals(1, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
+                mResolverParamsParcelCaptor.capture());
+        ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(1, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.contains(resolvrParams.servers, "2001:db8::1"));
         // Opportunistic mode.
-        assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
+        assertTrue(ArrayUtils.contains(resolvrParams.tlsServers, "2001:db8::1"));
         reset(mMockDnsResolver);
 
         cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
         mCellNetworkAgent.sendLinkProperties(cellLp);
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
-        assertEquals(2, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+                mResolverParamsParcelCaptor.capture());
+        resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(2, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         // Opportunistic mode.
-        assertEquals(2, tlsServers.getValue().length);
-        assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+        assertEquals(2, resolvrParams.tlsServers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         reset(mMockDnsResolver);
 
@@ -4887,18 +4884,16 @@
 
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(TLS_SPECIFIER), eq(TLS_SERVERS), eq(EMPTY_STRING_ARRAY));
-        assertEquals(2, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+                mResolverParamsParcelCaptor.capture());
+        resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(2, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         reset(mMockDnsResolver);
     }
 
     @Test
     public void testPrivateDnsSettingsChange() throws Exception {
-        ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
-
         // Clear any interactions that occur as a result of CS starting up.
         reset(mMockDnsResolver);
 
@@ -4913,9 +4908,7 @@
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
         waitForIdle();
         // CS tells netd about the empty DNS config for this network.
-        verify(mMockDnsResolver, never()).setResolverConfiguration(
-                anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
-                eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
+        verify(mMockDnsResolver, never()).setResolverConfiguration(any());
         verifyNoMoreInteractions(mMockDnsResolver);
 
         final LinkProperties cellLp = new LinkProperties();
@@ -4936,14 +4929,14 @@
         mCellNetworkAgent.connect(false);
         waitForIdle();
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
-        assertEquals(2, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+                mResolverParamsParcelCaptor.capture());
+        ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(2, resolvrParams.tlsServers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         // Opportunistic mode.
-        assertEquals(2, tlsServers.getValue().length);
-        assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+        assertEquals(2, resolvrParams.tlsServers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         reset(mMockDnsResolver);
         cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
@@ -4958,23 +4951,23 @@
 
         setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
-        assertEquals(2, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+                mResolverParamsParcelCaptor.capture());
+        resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(2, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         reset(mMockDnsResolver);
         cellNetworkCallback.assertNoCallback();
 
         setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
         verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                anyInt(), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
-        assertEquals(2, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
+                mResolverParamsParcelCaptor.capture());
+        resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(2, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.servers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
-        assertEquals(2, tlsServers.getValue().length);
-        assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
+        assertEquals(2, resolvrParams.tlsServers.length);
+        assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
                 new String[]{"2001:db8::1", "192.0.2.1"}));
         reset(mMockDnsResolver);
         cellNetworkCallback.assertNoCallback();
@@ -5826,9 +5819,7 @@
         mCellNetworkAgent.sendLinkProperties(cellLp);
         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
         verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
-        verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
-                eq(cellNetId), eq(EMPTY_STRING_ARRAY), any(), any(),
-                eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
+        verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
 
         verifyNoMoreInteractions(mMockNetd);
         verifyNoMoreInteractions(mMockDnsResolver);
@@ -5871,10 +5862,10 @@
         assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
 
         verify(mMockDnsResolver, times(1)).setResolverConfiguration(
-                eq(cellNetId), mStringArrayCaptor.capture(), any(), any(),
-                eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
-        assertEquals(1, mStringArrayCaptor.getValue().length);
-        assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "8.8.8.8"));
+                mResolverParamsParcelCaptor.capture());
+        ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
+        assertEquals(1, resolvrParams.servers.length);
+        assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8"));
 
         // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
         // linkproperties are cleaned up.
diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
index d983b65..f0453694 100644
--- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
+++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
@@ -20,6 +20,8 @@
 import android.net.ConnectivityManager.TYPE_MOBILE
 import android.net.ConnectivityManager.TYPE_WIFI
 import android.net.ConnectivityManager.TYPE_WIMAX
+import android.net.NetworkInfo.DetailedState.CONNECTED
+import android.net.NetworkInfo.DetailedState.DISCONNECTED
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import com.android.server.ConnectivityService.LegacyTypeTracker
@@ -32,8 +34,12 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
 
 const val UNSUPPORTED_TYPE = TYPE_WIMAX
 
@@ -89,4 +95,20 @@
         mTracker.add(UNSUPPORTED_TYPE, mobileNai)
         assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE))
     }
+
+    @Test
+    fun testBroadcastOnDisconnect() {
+        val mobileNai1 = mock(NetworkAgentInfo::class.java)
+        val mobileNai2 = mock(NetworkAgentInfo::class.java)
+        doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1)
+        mTracker.add(TYPE_MOBILE, mobileNai1)
+        verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE)
+        reset(mMockService)
+        doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2)
+        mTracker.add(TYPE_MOBILE, mobileNai2)
+        verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt())
+        mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
+        verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE)
+        verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE)
+    }
 }