Merge "APEX and system apps can't be installed in a streaming fashion."
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index d59270c..96110e1 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -15,6 +15,7 @@
  */
 package android.media;
 
+import android.annotation.CheckResult;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.Uri;
@@ -32,6 +33,7 @@
 import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints;
 import com.google.android.exoplayer2.extractor.TrackOutput;
 import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
+import com.google.android.exoplayer2.extractor.flac.FlacExtractor;
 import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
 import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
 import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
@@ -382,6 +384,7 @@
          * parse the input.
          */
         @NonNull
+        @CheckResult
         private static UnrecognizedInputFormatException createForExtractors(
                 @NonNull String... extractorNames) {
             StringBuilder builder = new StringBuilder();
@@ -536,7 +539,7 @@
                 }
             }
             if (mExtractor == null) {
-                UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool);
+                throw UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool);
             }
             return true;
         }
@@ -912,6 +915,7 @@
         extractorFactoriesByName.put("exo.Ac4Extractor", Ac4Extractor::new);
         extractorFactoriesByName.put("exo.AdtsExtractor", AdtsExtractor::new);
         extractorFactoriesByName.put("exo.AmrExtractor", AmrExtractor::new);
+        extractorFactoriesByName.put("exo.FlacExtractor", FlacExtractor::new);
         extractorFactoriesByName.put("exo.FlvExtractor", FlvExtractor::new);
         extractorFactoriesByName.put("exo.FragmentedMp4Extractor", FragmentedMp4Extractor::new);
         extractorFactoriesByName.put("exo.MatroskaExtractor", MatroskaExtractor::new);
diff --git a/api/current.txt b/api/current.txt
index 02fac79..81c4c92 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35687,6 +35687,7 @@
     field public static final String INCREMENTAL;
     field public static final int PREVIEW_SDK_INT;
     field public static final String RELEASE;
+    field @NonNull public static final String RELEASE_OR_CODENAME;
     field @Deprecated public static final String SDK;
     field public static final int SDK_INT;
     field public static final String SECURITY_PATCH;
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 73befec..3a2472e 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -65,7 +65,6 @@
         "src/config/ConfigListener.cpp",
         "src/config/ConfigManager.cpp",
         "src/experiment_ids.proto",
-        "src/external/GpuStatsPuller.cpp",
         "src/external/Perfetto.cpp",
         "src/external/PullResultReceiver.cpp",
         "src/external/puller_util.cpp",
@@ -111,7 +110,7 @@
     ],
 
     cflags: [
-        // "-DNEW_ENCODING_SCHEME",
+        "-DNEW_ENCODING_SCHEME",
     ],
 
     local_include_dirs: [
@@ -125,16 +124,15 @@
         "libprotoutil",
         "libstatslog",
         "libstatsmetadata",
-        "libstatssocket",
         "libsysutils",
     ],
     shared_libs: [
         "libbinder",
-        "libgraphicsenv",
         "libhidlbase",
         "libincident",
         "liblog",
         "libservices",
+        "libstatssocket",
         "libutils",
     ],
 }
@@ -278,7 +276,6 @@
         "tests/e2e/PartialBucket_e2e_test.cpp",
         "tests/e2e/ValueMetric_pull_e2e_test.cpp",
         "tests/e2e/WakelockDuration_e2e_test.cpp",
-        "tests/external/GpuStatsPuller_test.cpp",
         "tests/external/puller_util_test.cpp",
         "tests/external/StatsCallbackPuller_test.cpp",
         "tests/external/StatsPuller_test.cpp",
diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp
deleted file mode 100644
index 3229ba8..0000000
--- a/cmds/statsd/src/external/GpuStatsPuller.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GpuStatsPuller.h"
-
-#include <binder/IServiceManager.h>
-#include <graphicsenv/GpuStatsInfo.h>
-#include <graphicsenv/IGpuService.h>
-
-#include "logd/LogEvent.h"
-
-#include "stats_log_util.h"
-#include "statslog.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-using android::util::ProtoReader;
-
-GpuStatsPuller::GpuStatsPuller(const int tagId) : StatsPuller(tagId) {
-}
-
-static sp<IGpuService> getGpuService() {
-    const sp<IBinder> binder = defaultServiceManager()->checkService(String16("gpu"));
-    if (!binder) {
-        ALOGE("Failed to get gpu service");
-        return nullptr;
-    }
-
-    return interface_cast<IGpuService>(binder);
-}
-
-static bool pullGpuStatsGlobalInfo(const sp<IGpuService>& gpuService,
-                                   std::vector<std::shared_ptr<LogEvent>>* data) {
-    std::vector<GpuStatsGlobalInfo> stats;
-    status_t status = gpuService->getGpuStatsGlobalInfo(&stats);
-    if (status != OK) {
-        return false;
-    }
-
-    data->clear();
-    data->reserve(stats.size());
-    for (const auto& info : stats) {
-        std::shared_ptr<LogEvent> event = make_shared<LogEvent>(
-                android::util::GPU_STATS_GLOBAL_INFO, getWallClockNs(), getElapsedRealtimeNs());
-        if (!event->write(info.driverPackageName)) return false;
-        if (!event->write(info.driverVersionName)) return false;
-        if (!event->write((int64_t)info.driverVersionCode)) return false;
-        if (!event->write(info.driverBuildTime)) return false;
-        if (!event->write((int64_t)info.glLoadingCount)) return false;
-        if (!event->write((int64_t)info.glLoadingFailureCount)) return false;
-        if (!event->write((int64_t)info.vkLoadingCount)) return false;
-        if (!event->write((int64_t)info.vkLoadingFailureCount)) return false;
-        if (!event->write(info.vulkanVersion)) return false;
-        if (!event->write(info.cpuVulkanVersion)) return false;
-        if (!event->write(info.glesVersion)) return false;
-        if (!event->write((int64_t)info.angleLoadingCount)) return false;
-        if (!event->write((int64_t)info.angleLoadingFailureCount)) return false;
-        event->init();
-        data->emplace_back(event);
-    }
-
-    return true;
-}
-
-static bool pullGpuStatsAppInfo(const sp<IGpuService>& gpuService,
-                                std::vector<std::shared_ptr<LogEvent>>* data) {
-    std::vector<GpuStatsAppInfo> stats;
-    status_t status = gpuService->getGpuStatsAppInfo(&stats);
-    if (status != OK) {
-        return false;
-    }
-
-    data->clear();
-    data->reserve(stats.size());
-    for (const auto& info : stats) {
-        std::shared_ptr<LogEvent> event = make_shared<LogEvent>(
-                android::util::GPU_STATS_APP_INFO, getWallClockNs(), getElapsedRealtimeNs());
-        if (!event->write(info.appPackageName)) return false;
-        if (!event->write((int64_t)info.driverVersionCode)) return false;
-        if (!event->writeBytes(int64VectorToProtoByteString(info.glDriverLoadingTime)))  {
-            return false;
-        }
-        if (!event->writeBytes(int64VectorToProtoByteString(info.vkDriverLoadingTime))) {
-            return false;
-        }
-        if (!event->writeBytes(int64VectorToProtoByteString(info.angleDriverLoadingTime))) {
-            return false;
-        }
-        if (!event->write(info.cpuVulkanInUse)) return false;
-        if (!event->write(info.falsePrerotation)) return false;
-        if (!event->write(info.gles1InUse)) return false;
-        event->init();
-        data->emplace_back(event);
-    }
-
-    return true;
-}
-
-bool GpuStatsPuller::PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) {
-    const sp<IGpuService> gpuService = getGpuService();
-    if (!gpuService) {
-        return false;
-    }
-
-    switch (mTagId) {
-        case android::util::GPU_STATS_GLOBAL_INFO:
-            return pullGpuStatsGlobalInfo(gpuService, data);
-        case android::util::GPU_STATS_APP_INFO:
-            return pullGpuStatsAppInfo(gpuService, data);
-        default:
-            break;
-    }
-
-    return false;
-}
-
-static std::string protoOutputStreamToByteString(ProtoOutputStream& proto) {
-    if (!proto.size()) return "";
-
-    std::string byteString;
-    sp<ProtoReader> reader = proto.data();
-    while (reader->readBuffer() != nullptr) {
-        const size_t toRead = reader->currentToRead();
-        byteString.append((char*)reader->readBuffer(), toRead);
-        reader->move(toRead);
-    }
-
-    if (byteString.size() != proto.size()) return "";
-
-    return byteString;
-}
-
-std::string int64VectorToProtoByteString(const std::vector<int64_t>& value) {
-    if (value.empty()) return "";
-
-    ProtoOutputStream proto;
-    for (const auto& ele : value) {
-        proto.write(android::util::FIELD_TYPE_INT64 | android::util::FIELD_COUNT_REPEATED |
-                            1 /* field id */,
-                    (long long)ele);
-    }
-
-    return protoOutputStreamToByteString(proto);
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/GpuStatsPuller.h b/cmds/statsd/src/external/GpuStatsPuller.h
deleted file mode 100644
index 2da199c..0000000
--- a/cmds/statsd/src/external/GpuStatsPuller.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "StatsPuller.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-/**
- * Pull GpuStats from GpuService.
- */
-class GpuStatsPuller : public StatsPuller {
-public:
-    explicit GpuStatsPuller(const int tagId);
-    bool PullInternal(std::vector<std::shared_ptr<LogEvent>>* data) override;
-};
-
-// convert a int64_t vector into a byte string for proto message like:
-// message RepeatedInt64Wrapper {
-//   repeated int64 value = 1;
-// }
-std::string int64VectorToProtoByteString(const std::vector<int64_t>& value);
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 15d7e33..3ceff75 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -32,7 +32,6 @@
 #include "../logd/LogEvent.h"
 #include "../stats_log_util.h"
 #include "../statscompanion_util.h"
-#include "GpuStatsPuller.h"
 #include "StatsCallbackPuller.h"
 #include "TrainInfoPuller.h"
 #include "statslog.h"
@@ -51,15 +50,6 @@
     : kAllPullAtomInfo({
               // TrainInfo.
               {{.atomTag = android::util::TRAIN_INFO}, new TrainInfoPuller()},
-
-              // GpuStatsGlobalInfo
-              {{.atomTag = android::util::GPU_STATS_GLOBAL_INFO},
-               new GpuStatsPuller(android::util::GPU_STATS_GLOBAL_INFO)},
-
-              // GpuStatsAppInfo
-              {{.atomTag = android::util::GPU_STATS_APP_INFO},
-               new GpuStatsPuller(android::util::GPU_STATS_APP_INFO)},
-
       }),
       mNextPullTimeNs(NO_ALARM_UPDATE) {
 }
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
deleted file mode 100644
index ae92705..0000000
--- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "GpuStatsPuller_test"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <graphicsenv/GpuStatsInfo.h>
-#include <log/log.h>
-
-#include "src/external/GpuStatsPuller.h"
-#include "statslog.h"
-
-#ifdef __ANDROID__
-
-namespace android {
-namespace os {
-namespace statsd {
-
-// clang-format off
-static const std::string DRIVER_PACKAGE_NAME      = "TEST_DRIVER";
-static const std::string DRIVER_VERSION_NAME      = "TEST_DRIVER_VERSION";
-static const std::string APP_PACKAGE_NAME         = "TEST_APP";
-static const int64_t TIMESTAMP_WALLCLOCK          = 111;
-static const int64_t TIMESTAMP_ELAPSED            = 222;
-static const int64_t DRIVER_VERSION_CODE          = 333;
-static const int64_t DRIVER_BUILD_TIME            = 444;
-static const int64_t GL_LOADING_COUNT             = 3;
-static const int64_t GL_LOADING_FAILURE_COUNT     = 1;
-static const int64_t VK_LOADING_COUNT             = 4;
-static const int64_t VK_LOADING_FAILURE_COUNT     = 0;
-static const int64_t ANGLE_LOADING_COUNT          = 2;
-static const int64_t ANGLE_LOADING_FAILURE_COUNT  = 1;
-static const int64_t GL_DRIVER_LOADING_TIME_0     = 555;
-static const int64_t GL_DRIVER_LOADING_TIME_1     = 666;
-static const int64_t VK_DRIVER_LOADING_TIME_0     = 777;
-static const int64_t VK_DRIVER_LOADING_TIME_1     = 888;
-static const int64_t VK_DRIVER_LOADING_TIME_2     = 999;
-static const int64_t ANGLE_DRIVER_LOADING_TIME_0  = 1010;
-static const int64_t ANGLE_DRIVER_LOADING_TIME_1  = 1111;
-static const int32_t VULKAN_VERSION               = 1;
-static const int32_t CPU_VULKAN_VERSION           = 2;
-static const int32_t GLES_VERSION                 = 3;
-static const bool CPU_VULKAN_IN_USE               = true;
-static const bool FALSE_PREROTATION               = true;
-static const bool GLES_1_IN_USE                   = true;
-static const size_t NUMBER_OF_VALUES_GLOBAL       = 13;
-static const size_t NUMBER_OF_VALUES_APP          = 8;
-// clang-format on
-
-class MockGpuStatsPuller : public GpuStatsPuller {
-public:
-    MockGpuStatsPuller(const int tagId, vector<std::shared_ptr<LogEvent>>* data)
-        : GpuStatsPuller(tagId), mData(data){};
-
-private:
-    bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override {
-        *data = *mData;
-        return true;
-    }
-
-    vector<std::shared_ptr<LogEvent>>* mData;
-};
-
-class GpuStatsPuller_test : public ::testing::Test {
-public:
-    GpuStatsPuller_test() {
-        const ::testing::TestInfo* const test_info =
-                ::testing::UnitTest::GetInstance()->current_test_info();
-        ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-    }
-
-    ~GpuStatsPuller_test() {
-        const ::testing::TestInfo* const test_info =
-                ::testing::UnitTest::GetInstance()->current_test_info();
-        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
-    }
-};
-
-TEST_F(GpuStatsPuller_test, PullGpuStatsGlobalInfo) {
-    vector<std::shared_ptr<LogEvent>> inData, outData;
-    std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_GLOBAL_INFO,
-                                                            TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED);
-    EXPECT_TRUE(event->write(DRIVER_PACKAGE_NAME));
-    EXPECT_TRUE(event->write(DRIVER_VERSION_NAME));
-    EXPECT_TRUE(event->write(DRIVER_VERSION_CODE));
-    EXPECT_TRUE(event->write(DRIVER_BUILD_TIME));
-    EXPECT_TRUE(event->write(GL_LOADING_COUNT));
-    EXPECT_TRUE(event->write(GL_LOADING_FAILURE_COUNT));
-    EXPECT_TRUE(event->write(VK_LOADING_COUNT));
-    EXPECT_TRUE(event->write(VK_LOADING_FAILURE_COUNT));
-    EXPECT_TRUE(event->write(VULKAN_VERSION));
-    EXPECT_TRUE(event->write(CPU_VULKAN_VERSION));
-    EXPECT_TRUE(event->write(GLES_VERSION));
-    EXPECT_TRUE(event->write(ANGLE_LOADING_COUNT));
-    EXPECT_TRUE(event->write(ANGLE_LOADING_FAILURE_COUNT));
-    event->init();
-    inData.emplace_back(event);
-    MockGpuStatsPuller mockPuller(android::util::GPU_STATS_GLOBAL_INFO, &inData);
-    mockPuller.ForceClearCache();
-    mockPuller.Pull(&outData);
-
-    ASSERT_EQ(1, outData.size());
-    EXPECT_EQ(android::util::GPU_STATS_GLOBAL_INFO, outData[0]->GetTagId());
-    ASSERT_EQ(NUMBER_OF_VALUES_GLOBAL, outData[0]->size());
-    EXPECT_EQ(DRIVER_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value);
-    EXPECT_EQ(DRIVER_VERSION_NAME, outData[0]->getValues()[1].mValue.str_value);
-    EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[2].mValue.long_value);
-    EXPECT_EQ(DRIVER_BUILD_TIME, outData[0]->getValues()[3].mValue.long_value);
-    EXPECT_EQ(GL_LOADING_COUNT, outData[0]->getValues()[4].mValue.long_value);
-    EXPECT_EQ(GL_LOADING_FAILURE_COUNT, outData[0]->getValues()[5].mValue.long_value);
-    EXPECT_EQ(VK_LOADING_COUNT, outData[0]->getValues()[6].mValue.long_value);
-    EXPECT_EQ(VK_LOADING_FAILURE_COUNT, outData[0]->getValues()[7].mValue.long_value);
-    EXPECT_EQ(VULKAN_VERSION, outData[0]->getValues()[8].mValue.int_value);
-    EXPECT_EQ(CPU_VULKAN_VERSION, outData[0]->getValues()[9].mValue.int_value);
-    EXPECT_EQ(GLES_VERSION, outData[0]->getValues()[10].mValue.int_value);
-    EXPECT_EQ(ANGLE_LOADING_COUNT, outData[0]->getValues()[11].mValue.long_value);
-    EXPECT_EQ(ANGLE_LOADING_FAILURE_COUNT, outData[0]->getValues()[12].mValue.long_value);
-}
-
-TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) {
-    vector<std::shared_ptr<LogEvent>> inData, outData;
-    std::shared_ptr<LogEvent> event = make_shared<LogEvent>(android::util::GPU_STATS_APP_INFO,
-                                                            TIMESTAMP_WALLCLOCK, TIMESTAMP_ELAPSED);
-    EXPECT_TRUE(event->write(APP_PACKAGE_NAME));
-    EXPECT_TRUE(event->write(DRIVER_VERSION_CODE));
-    std::vector<int64_t> glDriverLoadingTime;
-    glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_0);
-    glDriverLoadingTime.emplace_back(GL_DRIVER_LOADING_TIME_1);
-    std::vector<int64_t> vkDriverLoadingTime;
-    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_0);
-    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_1);
-    vkDriverLoadingTime.emplace_back(VK_DRIVER_LOADING_TIME_2);
-    std::vector<int64_t> angleDriverLoadingTime;
-    angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_0);
-    angleDriverLoadingTime.emplace_back(ANGLE_DRIVER_LOADING_TIME_1);
-    EXPECT_TRUE(event->write(int64VectorToProtoByteString(glDriverLoadingTime)));
-    EXPECT_TRUE(event->write(int64VectorToProtoByteString(vkDriverLoadingTime)));
-    EXPECT_TRUE(event->write(int64VectorToProtoByteString(angleDriverLoadingTime)));
-    EXPECT_TRUE(event->write(CPU_VULKAN_IN_USE));
-    EXPECT_TRUE(event->write(FALSE_PREROTATION));
-    EXPECT_TRUE(event->write(GLES_1_IN_USE));
-    event->init();
-    inData.emplace_back(event);
-    MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData);
-    mockPuller.ForceClearCache();
-    mockPuller.Pull(&outData);
-
-    ASSERT_EQ(1, outData.size());
-    EXPECT_EQ(android::util::GPU_STATS_APP_INFO, outData[0]->GetTagId());
-    ASSERT_EQ(NUMBER_OF_VALUES_APP, outData[0]->size());
-    EXPECT_EQ(APP_PACKAGE_NAME, outData[0]->getValues()[0].mValue.str_value);
-    EXPECT_EQ(DRIVER_VERSION_CODE, outData[0]->getValues()[1].mValue.long_value);
-    EXPECT_EQ(int64VectorToProtoByteString(glDriverLoadingTime),
-              outData[0]->getValues()[2].mValue.str_value);
-    EXPECT_EQ(int64VectorToProtoByteString(vkDriverLoadingTime),
-              outData[0]->getValues()[3].mValue.str_value);
-    EXPECT_EQ(int64VectorToProtoByteString(angleDriverLoadingTime),
-              outData[0]->getValues()[4].mValue.str_value);
-    EXPECT_EQ(CPU_VULKAN_IN_USE, outData[0]->getValues()[5].mValue.int_value);
-    EXPECT_EQ(FALSE_PREROTATION, outData[0]->getValues()[6].mValue.int_value);
-    EXPECT_EQ(GLES_1_IN_USE, outData[0]->getValues()[7].mValue.int_value);
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
-#else
-GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index a291734..70b2db7 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -240,6 +240,13 @@
         public static final String RELEASE = getString("ro.build.version.release");
 
         /**
+         * The version string we show to the user; may be {@link #RELEASE} or
+         * {@link #CODENAME} if not a final release build.
+         */
+        @NonNull public static final String RELEASE_OR_CODENAME = getString(
+                "ro.build.version.release_or_codename");
+
+        /**
          * The base OS build the product is based on.
          */
         public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", "");
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 44f12a6..21a1e0f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -34,9 +34,11 @@
 import android.util.Log;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
 
 /**
  * Provides access to environment variables.
@@ -539,12 +541,21 @@
     @SystemApi
     public static @NonNull Collection<File> getInternalMediaDirectories() {
         final ArrayList<File> res = new ArrayList<>();
-        res.add(new File(Environment.getRootDirectory(), "media"));
-        res.add(new File(Environment.getOemDirectory(), "media"));
-        res.add(new File(Environment.getProductDirectory(), "media"));
+        addCanonicalFile(res, new File(Environment.getRootDirectory(), "media"));
+        addCanonicalFile(res, new File(Environment.getOemDirectory(), "media"));
+        addCanonicalFile(res, new File(Environment.getProductDirectory(), "media"));
         return res;
     }
 
+    private static void addCanonicalFile(List<File> list, File file) {
+        try {
+            list.add(file.getCanonicalFile());
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to resolve " + file + ": " + e);
+            list.add(file);
+        }
+    }
+
     /**
      * Return the primary shared/external storage directory. This directory may
      * not currently be accessible if it has been mounted by the user on their
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index 8990bdf..35fa37a 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -23,8 +23,6 @@
 import android.content.Context;
 import android.content.pm.DataLoaderParams;
 import android.os.RemoteException;
-import android.system.ErrnoException;
-import android.system.Os;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -193,116 +191,54 @@
     }
 
     /**
-     * Renames an Incremental path to a new path. If source path is a file, make a link from the old
-     * Incremental file to the new one. If source path is a dir, unbind old dir from Incremental
-     * Storage and bind the new one.
-     * <ol>
-     *     <li> For renaming a dir, dest dir will be created if not exists, and does not need to
-     *          be on the same Incremental storage as the source. </li>
-     *     <li> For renaming a file, dest file must be on the same Incremental storage as source.
-     *     </li>
-     * </ol>
+     * Set up an app's code path. The expected outcome of this method is:
+     * 1) The actual apk directory under /data/incremental is bind-mounted to the parent directory
+     * of {@code afterCodeFile}.
+     * 2) All the files under {@code beforeCodeFile} will show up under {@code afterCodeFile}.
      *
-     * @param sourcePath Absolute path to the source. Should be the same type as the destPath (file
-     *                   or dir). Expected to already exist and is an Incremental path.
-     * @param destPath   Absolute path to the destination.
-     * @throws IllegalArgumentException when 1) source does not exist, or 2) source and dest type
-     *                                  mismatch (one is file and the other is dir), or 3) source
-     *                                  path is not on Incremental File System,
-     * @throws IOException              when 1) cannot find the root path of the Incremental storage
-     *                                  of source, or 2) cannot retrieve the Incremental storage
-     *                                  instance of the source, or 3) renaming a file, but dest is
-     *                                  not on the same Incremental Storage, or 4) renaming a dir,
-     *                                  dest dir does not exist but fails to be created.
-     *                                  <p>
-     *                                  TODO(b/136132412): add unit tests
+     * @param beforeCodeFile Path that is currently bind-mounted and have APKs under it.
+     *                       Should no longer have any APKs after this method is called.
+     *                       Example: /data/app/vmdl*tmp
+     * @param afterCodeFile Path that should will have APKs after this method is called. Its parent
+     *                      directory should be bind-mounted to a directory under /data/incremental.
+     *                      Example: /data/app/~~[randomStringA]/[packageName]-[randomStringB]
+     * @throws IllegalArgumentException
+     * @throws IOException
+     * TODO(b/147371381): add unit tests
      */
-    public void rename(@NonNull String sourcePath, @NonNull String destPath) throws IOException {
-        final File source = new File(sourcePath);
-        final File dest = new File(destPath);
-        if (!source.exists()) {
-            throw new IllegalArgumentException("Path not exist: " + sourcePath);
+    public void renameCodePath(File beforeCodeFile, File afterCodeFile)
+            throws IllegalArgumentException, IOException {
+        final String beforeCodePath = beforeCodeFile.getAbsolutePath();
+        final String afterCodePathParent = afterCodeFile.getParentFile().getAbsolutePath();
+        if (!isIncrementalPath(beforeCodePath)) {
+            throw new IllegalArgumentException("Not an Incremental path: " + beforeCodePath);
         }
-        if (dest.exists()) {
-            throw new IllegalArgumentException("Target path already exists: " + destPath);
+        final String afterCodePathName = afterCodeFile.getName();
+        final Path apkStoragePath = Paths.get(beforeCodePath);
+        if (apkStoragePath == null || apkStoragePath.toAbsolutePath() == null) {
+            throw new IOException("Invalid source storage path for: " + beforeCodePath);
         }
-        if (source.isDirectory() && dest.exists() && dest.isFile()) {
-            throw new IllegalArgumentException(
-                    "Trying to rename a dir but destination is a file: " + destPath);
-        }
-        if (source.isFile() && dest.exists() && dest.isDirectory()) {
-            throw new IllegalArgumentException(
-                    "Trying to rename a file but destination is a dir: " + destPath);
-        }
-        if (!isIncrementalPath(sourcePath)) {
-            throw new IllegalArgumentException("Not an Incremental path: " + sourcePath);
-        }
-
-        Path storagePath = Paths.get(sourcePath);
-        if (source.isFile()) {
-            storagePath = getStoragePathForFile(source);
-        }
-        if (storagePath == null || storagePath.toAbsolutePath() == null) {
-            throw new IOException("Invalid source storage path for: " + sourcePath);
-        }
-        final IncrementalStorage storage = openStorage(storagePath.toAbsolutePath().toString());
-        if (storage == null) {
+        final IncrementalStorage apkStorage =
+                openStorage(apkStoragePath.toAbsolutePath().toString());
+        if (apkStorage == null) {
             throw new IOException("Failed to retrieve storage from Incremental Service.");
         }
-
-        if (source.isFile()) {
-            renameFile(storage, storagePath, source, dest);
-        } else {
-            renameDir(storage, storagePath, source, dest);
+        final IncrementalStorage linkedApkStorage = createStorage(afterCodePathParent, apkStorage,
+                IncrementalManager.CREATE_MODE_CREATE
+                        | IncrementalManager.CREATE_MODE_PERMANENT_BIND);
+        if (linkedApkStorage == null) {
+            throw new IOException("Failed to create linked storage at dir: " + afterCodePathParent);
         }
-    }
-
-    private void renameFile(IncrementalStorage storage, Path storagePath,
-            File source, File dest) throws IOException {
-        Path sourcePath = source.toPath();
-        Path destPath = dest.toPath();
-        if (!sourcePath.startsWith(storagePath)) {
-            throw new IOException("Path: " + source.getAbsolutePath() + " is not on storage at: "
-                    + storagePath.toString());
-        }
-        if (!destPath.startsWith(storagePath)) {
-            throw new IOException("Path: " + dest.getAbsolutePath() + " is not on storage at: "
-                    + storagePath.toString());
-        }
-        final Path sourceRelativePath = storagePath.relativize(sourcePath);
-        final Path destRelativePath = storagePath.relativize(destPath);
-        storage.moveFile(sourceRelativePath.toString(), destRelativePath.toString());
-
-    }
-
-    private void renameDir(IncrementalStorage storage, Path storagePath,
-            File source, File dest) throws IOException {
-        Path destPath = dest.toPath();
-        boolean usedMkdir = false;
-        try {
-            Os.mkdir(dest.getAbsolutePath(), 0755);
-            usedMkdir = true;
-        } catch (ErrnoException e) {
-            // Traditional mkdir fails but maybe we can create it on Incremental File System if
-            // the dest path is on the same Incremental storage as the source.
-            if (destPath.startsWith(storagePath)) {
-                storage.makeDirectories(storagePath.relativize(destPath).toString());
-            } else {
-                throw new IOException("Failed to create directory: " + dest.getAbsolutePath(), e);
+        linkedApkStorage.makeDirectory(afterCodePathName);
+        File[] files = beforeCodeFile.listFiles();
+        for (int i = 0; i < files.length; i++) {
+            if (files[i].isFile()) {
+                String fileName = files[i].getName();
+                apkStorage.makeLink(
+                        fileName, linkedApkStorage, afterCodePathName + "/" + fileName);
             }
         }
-        try {
-            storage.moveDir(source.getAbsolutePath(), dest.getAbsolutePath());
-        } catch (Exception ex) {
-            if (usedMkdir) {
-                try {
-                    Os.remove(dest.getAbsolutePath());
-                } catch (ErrnoException ignored) {
-                }
-            }
-            throw new IOException(
-                    "Failed to move " + source.getAbsolutePath() + " to " + dest.getAbsolutePath());
-        }
+        apkStorage.unBind(beforeCodePath);
     }
 
     /**
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index b6f5138..adfa885 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5205,6 +5205,7 @@
         /**
          * TelephonyProvider column name for allowed network types. Indicate which network types
          * are allowed. Default is -1.
+         * <P>Type: BIGINT (long) </P>
          */
         public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types";
     }
diff --git a/core/java/android/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 848868a..3ff6f54 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -41,6 +41,7 @@
 import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.SelectionEvent;
 import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationConstants;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassificationSessionId;
@@ -404,22 +405,27 @@
      */
     @NonNull
     public static TextClassifier getDefaultTextClassifierImplementation(@NonNull Context context) {
-        final String defaultTextClassifierPackageName =
-                context.getPackageManager().getDefaultTextClassifierPackageName();
-        if (TextUtils.isEmpty(defaultTextClassifierPackageName)) {
-            return TextClassifier.NO_OP;
-        }
-        if (defaultTextClassifierPackageName.equals(context.getPackageName())) {
-            throw new RuntimeException(
-                    "The default text classifier itself should not call the"
-                            + "getDefaultTextClassifierImplementation() method.");
-        }
         final TextClassificationManager tcm =
                 context.getSystemService(TextClassificationManager.class);
-        if (tcm != null) {
-            return tcm.getTextClassifier(TextClassifier.DEFAULT_SERVICE);
+        if (tcm == null) {
+            return TextClassifier.NO_OP;
         }
-        return TextClassifier.NO_OP;
+        TextClassificationConstants settings = new TextClassificationConstants();
+        if (settings.getUseDefaultTextClassifierAsDefaultImplementation()) {
+            final String defaultTextClassifierPackageName =
+                    context.getPackageManager().getDefaultTextClassifierPackageName();
+            if (TextUtils.isEmpty(defaultTextClassifierPackageName)) {
+                return TextClassifier.NO_OP;
+            }
+            if (defaultTextClassifierPackageName.equals(context.getPackageName())) {
+                throw new RuntimeException(
+                        "The default text classifier itself should not call the"
+                                + "getDefaultTextClassifierImplementation() method.");
+            }
+            return tcm.getTextClassifier(TextClassifier.DEFAULT_SERVICE);
+        } else {
+            return tcm.getTextClassifier(TextClassifier.LOCAL);
+        }
     }
 
     /** @hide **/
diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java
index ab2c4fc..ee3a8a7 100644
--- a/core/java/android/timezone/CountryTimeZones.java
+++ b/core/java/android/timezone/CountryTimeZones.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.icu.util.TimeZone;
 
 import java.util.ArrayList;
@@ -206,27 +205,47 @@
     }
 
     /**
-     * Returns a time zone for the country, if there is one, that matches the desired properties. If
-     * there are multiple matches and the {@code bias} is one of them then it is returned, otherwise
-     * an arbitrary match is returned based on the {@link #getEffectiveTimeZoneMappingsAt(long)}
-     * ordering.
+     * Returns a time zone for the country, if there is one, that matches the supplied properties.
+     * If there are multiple matches and the {@code bias} is one of them then it is returned,
+     * otherwise an arbitrary match is returned based on the {@link
+     * #getEffectiveTimeZoneMappingsAt(long)} ordering.
      *
+     * @param whenMillis the UTC time to match against
+     * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference
      * @param totalOffsetMillis the offset from UTC at {@code whenMillis}
      * @param isDst the Daylight Savings Time state at {@code whenMillis}. {@code true} means DST,
-     *     {@code false} means not DST, {@code null} means unknown
-     * @param dstOffsetMillis the part of {@code totalOffsetMillis} contributed by DST, only used if
-     *     {@code isDst} is {@code true}. The value can be {@code null} if the DST offset is
-     *     unknown
-     * @param whenMillis the UTC time to match against
-     * @param bias the time zone to prefer, can be {@code null}
+     *     {@code false} means not DST
+     * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if
+     *     there is no match
      */
     @Nullable
-    public OffsetResult lookupByOffsetWithBias(int totalOffsetMillis, @Nullable Boolean isDst,
-            @SuppressLint("AutoBoxing") @Nullable Integer dstOffsetMillis, long whenMillis,
-            @Nullable TimeZone bias) {
+    public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias,
+            int totalOffsetMillis, boolean isDst) {
         libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult =
                 mDelegate.lookupByOffsetWithBias(
-                        totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias);
+                        whenMillis, bias, totalOffsetMillis, isDst);
+        return delegateOffsetResult == null ? null :
+                new OffsetResult(
+                        delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch());
+    }
+
+    /**
+     * Returns a time zone for the country, if there is one, that matches the supplied properties.
+     * If there are multiple matches and the {@code bias} is one of them then it is returned,
+     * otherwise an arbitrary match is returned based on the {@link
+     * #getEffectiveTimeZoneMappingsAt(long)} ordering.
+     *
+     * @param whenMillis the UTC time to match against
+     * @param bias the time zone to prefer, can be {@code null} to indicate there is no preference
+     * @param totalOffsetMillis the offset from UTC at {@code whenMillis}
+     * @return an {@link OffsetResult} with information about a matching zone, or {@code null} if
+     *     there is no match
+     */
+    @Nullable
+    public OffsetResult lookupByOffsetWithBias(long whenMillis, @Nullable TimeZone bias,
+            int totalOffsetMillis) {
+        libcore.timezone.CountryTimeZones.OffsetResult delegateOffsetResult =
+                mDelegate.lookupByOffsetWithBias(whenMillis, bias, totalOffsetMillis);
         return delegateOffsetResult == null ? null :
                 new OffsetResult(
                         delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch());
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 36f4e53..4b3afba 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -80,7 +80,7 @@
             return null;
         }
         CountryTimeZones.OffsetResult offsetResult = countryTimeZones.lookupByOffsetWithBias(
-                offsetMillis, isDst, null /* dstOffsetMillis */, whenMillis, bias);
+                whenMillis, bias, offsetMillis, isDst);
         return offsetResult != null ? offsetResult.getTimeZone() : null;
     }
 
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index ed69513..3d5ac58 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -17,6 +17,7 @@
 package android.view.textclassifier;
 
 import android.annotation.Nullable;
+import android.content.Context;
 import android.provider.DeviceConfig;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -167,6 +168,16 @@
     static final String TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE =
             "textclassifier_service_package_override";
 
+    /**
+     * Whether to use the default system text classifier as the default text classifier
+     * implementation. The local text classifier is used if it is {@code false}.
+     *
+     * @see android.service.textclassifier.TextClassifierService#getDefaultTextClassifierImplementation(Context)
+     */
+    // TODO: Once the system health experiment is done, remove this together with local TC.
+    private static final String USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL =
+            "use_default_system_text_classifier_as_default_impl";
+
     private static final String DEFAULT_TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE = null;
     private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
     private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
@@ -209,7 +220,8 @@
     private static final boolean TEMPLATE_INTENT_FACTORY_ENABLED_DEFAULT = true;
     private static final boolean TRANSLATE_IN_CLASSIFICATION_ENABLED_DEFAULT = true;
     private static final boolean DETECT_LANGUAGES_FROM_TEXT_ENABLED_DEFAULT = true;
-    private static final float[] LANG_ID_CONTEXT_SETTINGS_DEFAULT = new float[] {20f, 1.0f, 0.4f};
+    private static final float[] LANG_ID_CONTEXT_SETTINGS_DEFAULT = new float[]{20f, 1.0f, 0.4f};
+    private static final boolean USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL_DEFAULT = true;
 
     @Nullable
     public String getTextClassifierServicePackageOverride() {
@@ -331,6 +343,13 @@
                 LANG_ID_CONTEXT_SETTINGS, LANG_ID_CONTEXT_SETTINGS_DEFAULT);
     }
 
+    public boolean getUseDefaultTextClassifierAsDefaultImplementation() {
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+                USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL,
+                USE_DEFAULT_SYSTEM_TEXT_CLASSIFIER_AS_DEFAULT_IMPL_DEFAULT);
+    }
+
     void dump(IndentingPrintWriter pw) {
         pw.println("TextClassificationConstants:");
         pw.increaseIndent();
@@ -378,6 +397,8 @@
                 .println();
         pw.printPair("textclassifier_service_package_override",
                 getTextClassifierServicePackageOverride()).println();
+        pw.printPair("use_default_system_text_classifier_as_default_impl",
+                getUseDefaultTextClassifierAsDefaultImplementation()).println();
         pw.decreaseIndent();
     }
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a43e4fe..65cad83 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2424,6 +2424,10 @@
                     offset += findViewById(R.id.content_preview_container).getHeight();
                 }
 
+                if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+                    offset += findViewById(R.id.tabs).getHeight();
+                }
+
                 int directShareHeight = 0;
                 rowsToShow = Math.min(4, rowsToShow);
                 for (int i = 0, childCount = recyclerView.getChildCount();
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index c6ed624..518911e 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -323,7 +323,7 @@
         result.append(System.getProperty("java.vm.version")); // such as 1.1.0
         result.append(" (Linux; U; Android ");
 
-        String version = Build.VERSION.RELEASE; // "1.0" or "3.4b5"
+        String version = Build.VERSION.RELEASE_OR_CODENAME; // "1.0" or "3.4b5"
         result.append(version.length() > 0 ? version : "1.0");
 
         // add the model for the release build
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index efa7d59..27d41d4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4878,6 +4878,19 @@
     <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
                 android:protectionLevel="signature|installer" />
 
+    <!-- Allows an app to log compat change usage.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.LOG_COMPAT_CHANGE"
+                android:protectionLevel="signature|privileged" />
+    <!-- Allows an app to read compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature|privileged" />
+    <!-- Allows an app to override compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Allows input events to be monitored. Very dangerous!  @hide -->
     <permission android:name="android.permission.MONITOR_INPUT"
                 android:protectionLevel="signature" />
diff --git a/core/res/res/layout/accessibility_button_chooser_item.xml b/core/res/res/layout/accessibility_button_chooser_item.xml
index d19e313..d6fd7aa 100644
--- a/core/res/res/layout/accessibility_button_chooser_item.xml
+++ b/core/res/res/layout/accessibility_button_chooser_item.xml
@@ -20,6 +20,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:clickable="true"
     android:gravity="center"
     android:paddingStart="16dp"
     android:paddingEnd="16dp"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b2d08a9..31e68e8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4343,4 +4343,7 @@
          Determines whether the specified key groups can be used to wake up the device. -->
     <bool name="config_wakeOnDpadKeyPress">true</bool>
     <bool name="config_wakeOnAssistKeyPress">true</bool>
+
+    <!-- Whether to default to an expanded list of users on the lock screen user switcher. -->
+    <bool name="config_expandLockScreenUserSwitcher">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c59d25f..2453bb1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3863,4 +3863,7 @@
 
   <!-- Toast message for background started foreground service while-in-use permission restriction feature -->
   <java-symbol type="string" name="allow_while_in_use_permission_in_fgs" />
+
+  <!-- Whether to expand the lock screen user switcher by default -->
+  <java-symbol type="bool" name="config_expandLockScreenUserSwitcher" />
 </resources>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index ee93b39..59335a5 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -111,6 +111,10 @@
     <uses-permission android:name="android.permission.MOVE_PACKAGE" />
     <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
 
+    <!-- gating and logging permissions -->
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+
     <!-- os storage test permissions -->
     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
     <uses-permission android:name="android.permission.ASEC_ACCESS" />
diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
index bf78203..7733559 100644
--- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -90,18 +90,18 @@
     }
 
     @Test
-    public void testValidAtomicFormula_stringValue_appCertificateAutoHashed() {
+    public void testValidAtomicFormula_stringValue_appCertificateIsNotAutoHashed() {
         String appCert = "cert";
         StringAtomicFormula stringAtomicFormula =
                 new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, appCert);
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
-        assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCert);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+        assertThat(stringAtomicFormula.getValue()).matches(appCert);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
-    public void testValidAtomicFormula_stringValue_installerCertificateAutoHashed() {
+    public void testValidAtomicFormula_stringValue_installerCertificateIsNotAutoHashed() {
         String installerCert = "cert";
         StringAtomicFormula stringAtomicFormula =
                 new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE,
@@ -109,8 +109,8 @@
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(
                 AtomicFormula.INSTALLER_CERTIFICATE);
-        assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCert);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+        assertThat(stringAtomicFormula.getValue()).matches(installerCert);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
index c180602..dc03167 100644
--- a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
@@ -40,7 +40,7 @@
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
         assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
@@ -53,8 +53,8 @@
                 (AtomicFormula.StringAtomicFormula) formula;
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
-        assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCertificate);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+        assertThat(stringAtomicFormula.getValue()).matches(appCertificate);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
@@ -68,7 +68,7 @@
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
         assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
@@ -81,8 +81,8 @@
                 (AtomicFormula.StringAtomicFormula) formula;
 
         assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_CERTIFICATE);
-        assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCertificate);
-        assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+        assertThat(stringAtomicFormula.getValue()).matches(installerCertificate);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/os/BuildTest.java b/core/tests/coretests/src/android/os/BuildTest.java
index decc768..2295eb9 100644
--- a/core/tests/coretests/src/android/os/BuildTest.java
+++ b/core/tests/coretests/src/android/os/BuildTest.java
@@ -60,7 +60,7 @@
         assertNotEmpty("BRAND", Build.BRAND);
         assertNotEmpty("MODEL", Build.MODEL);
         assertNotEmpty("VERSION.INCREMENTAL", Build.VERSION.INCREMENTAL);
-        assertNotEmpty("VERSION.RELEASE", Build.VERSION.RELEASE);
+        assertNotEmpty("VERSION.RELEASE", Build.VERSION.RELEASE_OR_CODENAME);
         assertNotEmpty("TYPE", Build.TYPE);
         Assert.assertNotNull("TAGS", Build.TAGS); // TAGS is allowed to be empty.
         assertNotEmpty("FINGERPRINT", Build.FINGERPRINT);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index df6b906..ce71beb 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -38,6 +38,7 @@
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -355,6 +356,7 @@
         // enable the work tab feature flag
         ResolverActivity.ENABLE_TABBED_VIEW = true;
 
+        markWorkProfileUserAvailable();
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -1209,17 +1211,24 @@
         // enable the work tab feature flag
         ResolverActivity.ENABLE_TABBED_VIEW = true;
         int personalProfileTargets = 3;
+        int otherProfileTargets = 1;
         List<ResolvedComponentInfo> personalResolvedComponentInfos =
-                createResolvedComponentsForTest(personalProfileTargets);
+                createResolvedComponentsForTestWithOtherProfile(
+                        personalProfileTargets + otherProfileTargets, /* userID */ 10);
         int workProfileTargets = 4;
         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
                 workProfileTargets);
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+                Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
+        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class),
+                eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType("TestType");
         markWorkProfileUserAvailable();
@@ -1229,8 +1238,6 @@
         waitForIdle();
 
         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
-        // The work list adapter must only be filled when we open the work tab
-        assertThat(activity.getWorkListAdapter().getCount(), is(0));
         onView(withText(R.string.resolver_work_tab)).perform(click());
         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
         assertThat(activity.getPersonalListAdapter().getCount(), is(personalProfileTargets));
@@ -1243,11 +1250,22 @@
         ResolverActivity.ENABLE_TABBED_VIEW = true;
         markWorkProfileUserAvailable();
         int workProfileTargets = 4;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos =
                 createResolvedComponentsForTest(workProfileTargets);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class),
+                eq(UserHandle.SYSTEM)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         Intent sendIntent = createSendTextIntent();
         sendIntent.setType("TestType");
 
@@ -1357,6 +1375,20 @@
         return infoList;
     }
 
+    private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
+            int numberOfResults, int userId) {
+        List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+        for (int i = 0; i < numberOfResults; i++) {
+            if (i == 0) {
+                infoList.add(
+                        ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+            } else {
+                infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+            }
+        }
+        return infoList;
+    }
+
     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithUserId(
             int numberOfResults, int userId) {
         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index eee62bb..a68b5908 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -16,10 +16,15 @@
 
 package com.android.internal.app;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.annotation.Nullable;
+import android.app.prediction.AppPredictionContext;
+import android.app.prediction.AppPredictionManager;
+import android.app.prediction.AppPredictor;
 import android.app.usage.UsageStatsManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -40,6 +45,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
+import org.mockito.Mockito;
+
 import java.util.function.Function;
 
 public class ChooserWrapperActivity extends ChooserActivity {
@@ -173,6 +180,12 @@
         return mMultiProfilePagerAdapter.getCurrentUserHandle();
     }
 
+    @Override
+    public Context createContextAsUser(UserHandle user, int flags) {
+        // return the current context as a work profile doesn't really exist in these tests
+        return getApplicationContext();
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 911490f..5f4194a 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -225,6 +225,7 @@
         // enable the work tab feature flag
         ResolverActivity.ENABLE_TABBED_VIEW = true;
 
+        markWorkProfileUserAvailable();
         Intent sendIntent = createSendImageIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -246,7 +247,6 @@
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
-
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -443,7 +443,7 @@
         // enable the work tab feature flag
         ResolverActivity.ENABLE_TABBED_VIEW = true;
         List<ResolvedComponentInfo> personalResolvedComponentInfos =
-                createResolvedComponentsForTest(3);
+                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
@@ -451,6 +451,11 @@
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class),
+                eq(UserHandle.SYSTEM)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         Intent sendIntent = createSendImageIntent();
         markWorkProfileUserAvailable();
 
@@ -478,17 +483,20 @@
                 Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
-                eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
+                eq(sOverrides.workProfileUserHandle)))
+                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
-                eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
+                eq(sOverrides.workProfileUserHandle)))
+                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
@@ -502,7 +510,7 @@
         onView(withText(R.string.resolver_work_tab)).perform(click());
 
         assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
-        assertThat(activity.getPersonalListAdapter().getCount(), is(3));
+        assertThat(activity.getPersonalListAdapter().getCount(), is(2));
     }
 
     @Test
@@ -511,14 +519,20 @@
         ResolverActivity.ENABLE_TABBED_VIEW = true;
         markWorkProfileUserAvailable();
         List<ResolvedComponentInfo> personalResolvedComponentInfos =
-                createResolvedComponentsForTest(3);
+                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class),
+                eq(UserHandle.SYSTEM)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         Intent sendIntent = createSendImageIntent();
 
         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
@@ -536,14 +550,20 @@
         ResolverActivity.ENABLE_TABBED_VIEW = true;
         markWorkProfileUserAvailable();
         List<ResolvedComponentInfo> personalResolvedComponentInfos =
-                createResolvedComponentsForTest(3);
+                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
         List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class),
+                eq(UserHandle.SYSTEM)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         Intent sendIntent = createSendImageIntent();
         ResolveInfo[] chosen = new ResolveInfo[1];
         sOverrides.onSafelyStartCallback = targetInfo -> {
@@ -587,17 +607,20 @@
                 Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
-                eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
+                eq(sOverrides.workProfileUserHandle)))
+                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
-                eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
+                eq(sOverrides.workProfileUserHandle)))
+                .thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
-                Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
+                Mockito.isA(List.class)))
+                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
         when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                 Mockito.anyBoolean(),
                 Mockito.isA(List.class),
@@ -678,6 +701,20 @@
         return infoList;
     }
 
+    private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
+            int numberOfResults, int userId) {
+        List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+        for (int i = 0; i < numberOfResults; i++) {
+            if (i == 0) {
+                infoList.add(
+                        ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+            } else {
+                infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
+            }
+        }
+        return infoList;
+    }
+
     private void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
diff --git a/data/etc/com.android.settings.xml b/data/etc/com.android.settings.xml
index a200a51..fe1182e 100644
--- a/data/etc/com.android.settings.xml
+++ b/data/etc/com.android.settings.xml
@@ -26,6 +26,7 @@
         <permission name="android.permission.DELETE_PACKAGES"/>
         <permission name="android.permission.FORCE_STOP_PACKAGES"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+        <permission name="android.permission.LOG_COMPAT_CHANGE" />
         <permission name="android.permission.MANAGE_DEBUGGING"/>
         <permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
         <permission name="android.permission.MANAGE_FINGERPRINT"/>
@@ -37,8 +38,10 @@
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.MOVE_PACKAGE"/>
+        <permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" />
         <permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+        <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.READ_SEARCH_INDEXABLES"/>
         <permission name="android.permission.REBOOT"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index b5eba09..b9a7e22 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -366,6 +366,10 @@
         <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
         <!-- Permission required for Tethering CTS tests. -->
         <permission name="android.permission.TETHER_PRIVILEGED"/>
+        <!-- Permissions required for ganting and logging -->
+        <permission name="android.permission.LOG_COMPAT_CHANGE" />
+        <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+        <permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" />
         <!-- Permissions required to test ambient display. -->
         <permission name="android.permission.READ_DREAM_STATE" />
         <permission name="android.permission.WRITE_DREAM_STATE" />
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 9c8345d..6212493 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -10,6 +10,7 @@
         "androidx.appcompat_appcompat",
         "androidx.lifecycle_lifecycle-runtime",
         "androidx.mediarouter_mediarouter-nodeps",
+        "iconloader",
 
         "SettingsLibHelpUtils",
         "SettingsLibRestrictedLockUtils",
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index de523d9..213e365 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -3,6 +3,7 @@
 import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -13,6 +14,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.location.LocationManager;
 import android.media.AudioManager;
@@ -27,8 +29,11 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.UserIcons;
+import com.android.launcher3.icons.IconFactory;
 import com.android.settingslib.drawable.UserIconDrawable;
 
 import java.text.NumberFormat;
@@ -424,6 +429,19 @@
         return state;
     }
 
+    /**
+     * Get the {@link Drawable} that represents the app icon
+     */
+    public static @NonNull Drawable getBadgedIcon(
+            @NonNull Context context, @NonNull ApplicationInfo appInfo) {
+        final UserHandle user = UserHandle.getUserHandleForUid(appInfo.uid);
+        try (IconFactory iconFactory = IconFactory.obtain(context)) {
+            final Bitmap iconBmp = iconFactory.createBadgedIconBitmap(
+                    appInfo.loadUnbadgedIcon(context.getPackageManager()), user, false).icon;
+            return new BitmapDrawable(context.getResources(), iconBmp);
+        }
+    }
+
     private static boolean isNotInIwlan(ServiceState serviceState) {
         final NetworkRegistrationInfo networkRegWlan = serviceState.getNetworkRegistrationInfo(
                 NetworkRegistrationInfo.DOMAIN_PS,
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 19c6664..af72888 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -59,6 +59,7 @@
 
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.Utils;
 
 import java.io.File;
 import java.io.IOException;
@@ -495,7 +496,7 @@
             return;
         }
         synchronized (entry) {
-            entry.ensureIconLocked(mContext, mDrawableFactory);
+            entry.ensureIconLocked(mContext);
         }
     }
 
@@ -1216,7 +1217,7 @@
                                 AppEntry entry = mAppEntries.get(i);
                                 if (entry.icon == null || !entry.mounted) {
                                     synchronized (entry) {
-                                        if (entry.ensureIconLocked(mContext, mDrawableFactory)) {
+                                        if (entry.ensureIconLocked(mContext)) {
                                             if (!mRunning) {
                                                 mRunning = true;
                                                 Message m = mMainHandler.obtainMessage(
@@ -1587,10 +1588,10 @@
             }
         }
 
-        boolean ensureIconLocked(Context context, IconDrawableFactory drawableFactory) {
+        boolean ensureIconLocked(Context context) {
             if (this.icon == null) {
                 if (this.apkFile.exists()) {
-                    this.icon = drawableFactory.getBadgedIcon(info);
+                    this.icon = Utils.getBadgedIcon(context, info);
                     return true;
                 } else {
                     this.mounted = false;
@@ -1601,7 +1602,7 @@
                 // its icon.
                 if (this.apkFile.exists()) {
                     this.mounted = true;
-                    this.icon = drawableFactory.getBadgedIcon(info);
+                    this.icon = Utils.getBadgedIcon(context, info);
                     return true;
                 }
             }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6a89b71..1d679c7 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -223,6 +223,11 @@
     <!-- permissions required for CTS test - PhoneStateListenerTest -->
     <uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" />
 
+    <!-- Permissions required for ganting and logging -->
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+    <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/>
+
     <!-- Permission required for CTS test - UiModeManagerTest -->
     <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 139a8c3..1fe967b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -645,7 +645,6 @@
         <activity android:name=".controls.management.ControlsProviderSelectorActivity"
                   android:label="Controls Providers"
                   android:theme="@style/Theme.ControlsManagement"
-                  android:exported="true"
                   android:showForAllUsers="true"
                   android:excludeFromRecents="true"
                   android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index a6f1d84..7de1557 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -19,9 +19,12 @@
 import android.app.PendingIntent
 import android.content.BroadcastReceiver
 import android.content.ComponentName
+import android.content.ContentResolver
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
+import android.database.ContentObserver
+import android.net.Uri
 import android.os.Environment
 import android.os.UserHandle
 import android.provider.Settings
@@ -30,6 +33,7 @@
 import android.util.ArrayMap
 import android.util.Log
 import com.android.internal.annotations.GuardedBy
+import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.DumpController
 import com.android.systemui.Dumpable
 import com.android.systemui.broadcast.BroadcastDispatcher
@@ -53,15 +57,16 @@
     private val uiController: ControlsUiController,
     private val bindingController: ControlsBindingController,
     private val listingController: ControlsListingController,
-    broadcastDispatcher: BroadcastDispatcher,
+    private val broadcastDispatcher: BroadcastDispatcher,
     optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
     dumpController: DumpController
 ) : Dumpable, ControlsController {
 
     companion object {
         private const val TAG = "ControlsControllerImpl"
-        const val CONTROLS_AVAILABLE = "systemui.controls_available"
-        const val USER_CHANGE_RETRY_DELAY = 500L // ms
+        internal const val CONTROLS_AVAILABLE = "systemui.controls_available"
+        internal val URI = Settings.Secure.getUriFor(CONTROLS_AVAILABLE)
+        private const val USER_CHANGE_RETRY_DELAY = 500L // ms
     }
 
     // Map of map: ComponentName -> (String -> ControlInfo).
@@ -69,9 +74,11 @@
     @GuardedBy("currentFavorites")
     private val currentFavorites = ArrayMap<ComponentName, MutableMap<String, ControlInfo>>()
 
-    private var userChanging = true
-    override var available = Settings.Secure.getInt(
-            context.contentResolver, CONTROLS_AVAILABLE, 0) != 0
+    private var userChanging: Boolean = true
+
+    private val contentResolver: ContentResolver
+        get() = context.contentResolver
+    override var available = Settings.Secure.getInt(contentResolver, CONTROLS_AVAILABLE, 0) != 0
         private set
 
     private var currentUser = context.user
@@ -95,8 +102,8 @@
         val fileName = Environment.buildPath(
                 userContext.filesDir, ControlsFavoritePersistenceWrapper.FILE_NAME)
         persistenceWrapper.changeFile(fileName)
-        available = Settings.Secure.getIntForUser(
-                context.contentResolver, CONTROLS_AVAILABLE, 0) != 0
+        available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
+                /* default */ 0, newUser.identifier) != 0
         synchronized(currentFavorites) {
             currentFavorites.clear()
         }
@@ -123,6 +130,25 @@
         }
     }
 
+    @VisibleForTesting
+    internal val settingObserver = object : ContentObserver(null) {
+        override fun onChange(selfChange: Boolean, uri: Uri, userId: Int) {
+            // Do not listen to changes in the middle of user change, those will be read by the
+            // user-switch receiver.
+            if (userChanging || userId != currentUserId) {
+                return
+            }
+            available = Settings.Secure.getIntForUser(contentResolver, CONTROLS_AVAILABLE,
+                    /* default */ 0, currentUserId) != 0
+            synchronized(currentFavorites) {
+                currentFavorites.clear()
+            }
+            if (available) {
+                loadFavorites()
+            }
+        }
+    }
+
     init {
         dumpController.registerDumpable(this)
         if (available) {
@@ -135,6 +161,7 @@
                 executor,
                 UserHandle.ALL
         )
+        contentResolver.registerContentObserver(URI, false, settingObserver, UserHandle.USER_ALL)
     }
 
     private fun confirmAvailability(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index fad2d94..88b19b5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -34,14 +34,17 @@
 import android.widget.TextView
 
 import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.systemui.R
 
 const val MIN_LEVEL = 0
 const val MAX_LEVEL = 10000
+private const val UPDATE_DELAY_IN_MILLIS = 2000L
 
 class ControlViewHolder(
     val layout: ViewGroup,
-    val controlsController: ControlsController
+    val controlsController: ControlsController,
+    val uiExecutor: DelayableExecutor
 ) {
     val icon: ImageView = layout.requireViewById(R.id.icon)
     val status: TextView = layout.requireViewById(R.id.status)
@@ -52,6 +55,7 @@
     val clipLayer: ClipDrawable
     val gd: GradientDrawable
     lateinit var cws: ControlWithState
+    var cancelUpdate: Runnable? = null
 
     init {
         val ld = layout.getBackground() as LayerDrawable
@@ -63,6 +67,8 @@
     fun bindData(cws: ControlWithState) {
         this.cws = cws
 
+        cancelUpdate?.run()
+
         val (status, template) = cws.control?.let {
             title.setText(it.getTitle())
             subtitle.setText(it.getSubtitle())
@@ -86,6 +92,27 @@
         findBehavior(status, template).apply(this, cws)
     }
 
+    fun actionResponse(@ControlAction.ResponseResult response: Int) {
+        val text = when (response) {
+            ControlAction.RESPONSE_OK -> "Success"
+            ControlAction.RESPONSE_FAIL -> "Error"
+            else -> ""
+        }
+
+        if (!text.isEmpty()) {
+            val previousText = status.getText()
+            val previousTextExtra = statusExtra.getText()
+
+            cancelUpdate = uiExecutor.executeDelayed({
+                    status.setText(previousText)
+                    statusExtra.setText(previousTextExtra)
+                }, UPDATE_DELAY_IN_MILLIS)
+
+            status.setText(text)
+            statusExtra.setText("")
+        }
+    }
+
     fun action(action: ControlAction) {
         controlsController.action(cws.ci, action)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
index b07a75d..d70c86f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -22,6 +22,8 @@
 import android.view.ViewGroup
 
 interface ControlsUiController {
+    val available: Boolean
+
     fun show(parent: ViewGroup)
     fun hide()
     fun onRefreshState(componentName: ComponentName, controls: List<Control>)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index a777faf..ed521e3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -38,10 +38,10 @@
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.R
+import com.android.systemui.util.concurrency.DelayableExecutor
 
 import dagger.Lazy
 
-import java.util.concurrent.Executor
 import javax.inject.Inject
 import javax.inject.Singleton
 
@@ -104,18 +104,23 @@
     }
 }
 
+private data class ControlKey(val componentName: ComponentName, val controlId: String)
+
 @Singleton
 class ControlsUiControllerImpl @Inject constructor (
     val controlsController: Lazy<ControlsController>,
     val context: Context,
-    @Main val uiExecutor: Executor
+    @Main val uiExecutor: DelayableExecutor
 ) : ControlsUiController {
 
     private lateinit var controlInfos: List<ControlInfo>
-    private val controlsById = mutableMapOf<Pair<ComponentName, String>, ControlWithState>()
-    private val controlViewsById = mutableMapOf<String, ControlViewHolder>()
+    private val controlsById = mutableMapOf<ControlKey, ControlWithState>()
+    private val controlViewsById = mutableMapOf<ControlKey, ControlViewHolder>()
     private lateinit var parent: ViewGroup
 
+    override val available: Boolean
+        get() = controlsController.get().available
+
     override fun show(parent: ViewGroup) {
         Log.d(TAG, "show()")
 
@@ -125,7 +130,7 @@
 
         controlInfos.map {
             ControlWithState(it, null)
-        }.associateByTo(controlsById) { Pair(it.ci.component, it.ci.controlId) }
+        }.associateByTo(controlsById) { ControlKey(it.ci.component, it.ci.controlId) }
 
         if (controlInfos.isEmpty()) {
             showInitialSetupView()
@@ -178,9 +183,10 @@
             val item = inflater.inflate(
                 R.layout.controls_base_item, lastRow, false) as ViewGroup
             lastRow.addView(item)
-            val cvh = ControlViewHolder(item, controlsController.get())
-            cvh.bindData(controlsById.get(Pair(it.component, it.controlId))!!)
-            controlViewsById.put(it.controlId, cvh)
+            val cvh = ControlViewHolder(item, controlsController.get(), uiExecutor)
+            val key = ControlKey(it.component, it.controlId)
+            cvh.bindData(controlsById.getValue(key))
+            controlViewsById.put(key, cvh)
         }
 
         if ((controlInfos.size % 2) == 1) {
@@ -205,21 +211,24 @@
     override fun onRefreshState(componentName: ComponentName, controls: List<Control>) {
         Log.d(TAG, "onRefreshState()")
         controls.forEach { c ->
-            controlsById.get(Pair(componentName, c.getControlId()))?.let {
+            controlsById.get(ControlKey(componentName, c.getControlId()))?.let {
                 Log.d(TAG, "onRefreshState() for id: " + c.getControlId())
                 val cws = ControlWithState(it.ci, c)
-                controlsById.put(Pair(componentName, c.getControlId()), cws)
+                val key = ControlKey(componentName, c.getControlId())
+                controlsById.put(key, cws)
 
                 uiExecutor.execute {
-                    controlViewsById.get(c.getControlId())?.bindData(cws)
+                    controlViewsById.get(key)?.bindData(cws)
                 }
             }
         }
     }
 
     override fun onActionResponse(componentName: ComponentName, controlId: String, response: Int) {
-        Log.d(TAG, "onActionResponse()")
-        TODO("not implemented")
+        val key = ControlKey(componentName, controlId)
+        uiExecutor.execute {
+            controlViewsById.get(key)?.actionResponse(response)
+        }
     }
 
     private fun createRow(inflater: LayoutInflater, parent: ViewGroup): ViewGroup {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 45c07a3..082b065 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1899,9 +1899,7 @@
     }
 
     private boolean shouldShowControls() {
-        return isCurrentUserOwner()
-                && !mKeyguardManager.isDeviceLocked()
-                && Settings.Secure.getInt(mContext.getContentResolver(),
-                        "systemui.controls_available", 0) == 1;
+        return !mKeyguardManager.isDeviceLocked()
+                && mControlsUiController.getAvailable();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 0134aa3..5de6d1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -169,7 +169,7 @@
         if (DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)) {
             v.setText(mContext.getString(
                     com.android.internal.R.string.bugreport_status,
-                    Build.VERSION.RELEASE,
+                    Build.VERSION.RELEASE_OR_CODENAME,
                     Build.ID));
             v.setVisibility(View.VISIBLE);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
index 9e3e94c..6c69718 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -36,6 +36,7 @@
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.media.session.PlaybackState;
+import android.os.Handler;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -370,6 +371,13 @@
         if (mSeamless == null) {
             return;
         }
+        Handler handler = mSeamless.getHandler();
+        handler.post(() -> {
+            updateChipInternal(device);
+        });
+    }
+
+    private void updateChipInternal(MediaDevice device) {
         ColorStateList fgTintList = ColorStateList.valueOf(mForegroundColor);
 
         // Update the outline color
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 2907cd4..8dfcb0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -134,6 +134,8 @@
         mBroadcastDispatcher.registerReceiver(
                 mReceiver, filter, null /* handler */, UserHandle.SYSTEM);
 
+        mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
+
         mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
 
         filter = new IntentFilter();
@@ -258,22 +260,20 @@
                         && mUserManager.canAddMoreUsers();
                 boolean createIsRestricted = !addUsersWhenLocked;
 
-                if (!mSimpleUserSwitcher) {
-                    if (guestRecord == null) {
-                        if (canCreateGuest) {
-                            guestRecord = new UserRecord(null /* info */, null /* picture */,
-                                    true /* isGuest */, false /* isCurrent */,
-                                    false /* isAddUser */, createIsRestricted, canSwitchUsers);
-                            checkIfAddUserDisallowedByAdminOnly(guestRecord);
-                            records.add(guestRecord);
-                        }
-                    } else {
-                        int index = guestRecord.isCurrent ? 0 : records.size();
-                        records.add(index, guestRecord);
+                if (guestRecord == null) {
+                    if (canCreateGuest) {
+                        guestRecord = new UserRecord(null /* info */, null /* picture */,
+                                true /* isGuest */, false /* isCurrent */,
+                                false /* isAddUser */, createIsRestricted, canSwitchUsers);
+                        checkIfAddUserDisallowedByAdminOnly(guestRecord);
+                        records.add(guestRecord);
                     }
+                } else {
+                    int index = guestRecord.isCurrent ? 0 : records.size();
+                    records.add(index, guestRecord);
                 }
 
-                if (!mSimpleUserSwitcher && canCreateUser) {
+                if (canCreateUser) {
                     UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
                             false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
                             createIsRestricted, canSwitchUsers);
@@ -562,8 +562,7 @@
 
     private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
         public void onChange(boolean selfChange) {
-            mSimpleUserSwitcher = Settings.Global.getInt(mContext.getContentResolver(),
-                    SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
+            mSimpleUserSwitcher = shouldUseSimpleUserSwitcher();
             mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
             refreshUsers(UserHandle.USER_NULL);
@@ -579,6 +578,7 @@
             final UserRecord u = mUsers.get(i);
             pw.print("    "); pw.println(u.toString());
         }
+        pw.println("mSimpleUserSwitcher=" + mSimpleUserSwitcher);
     }
 
     public String getCurrentUserName(Context context) {
@@ -717,6 +717,13 @@
         }
     }
 
+    private boolean shouldUseSimpleUserSwitcher() {
+        int defaultSimpleUserSwitcher = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_expandLockScreenUserSwitcher) ? 1 : 0;
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                SIMPLE_USER_SWITCHER_GLOBAL_SETTING, defaultSimpleUserSwitcher) != 0;
+    }
+
     public void startActivity(Intent intent) {
         mActivityStarter.startActivity(intent, true);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index a60ca62..49ada1a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -158,7 +158,7 @@
 
         String demoTime = "1010"; // 10:10, a classic choice of horologists
         try {
-            String[] versionParts = android.os.Build.VERSION.RELEASE.split("\\.");
+            String[] versionParts = android.os.Build.VERSION.RELEASE_OR_CODENAME.split("\\.");
             int majorVersion = Integer.valueOf(versionParts[0]);
             demoTime = String.format("%02d00", majorVersion % 24);
         } catch (IllegalArgumentException ex) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index 897091f..e3bcdc8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -32,12 +32,13 @@
 import com.android.systemui.DumpController
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.ControlStatus
+import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
@@ -82,7 +83,7 @@
     private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver>
 
     private lateinit var delayableExecutor: FakeExecutor
-    private lateinit var controller: ControlsController
+    private lateinit var controller: ControlsControllerImpl
 
     companion object {
         fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
@@ -416,5 +417,70 @@
         verify(listingController).changeUser(UserHandle.of(otherUser))
         assertTrue(controller.getFavoriteControls().isEmpty())
         assertEquals(otherUser, controller.currentUserId)
+        assertTrue(controller.available)
     }
-}
\ No newline at end of file
+
+    @Test
+    fun testDisableFeature_notAvailable() {
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
+        controller.settingObserver.onChange(false, ControlsControllerImpl.URI, 0)
+        assertFalse(controller.available)
+    }
+
+    @Test
+    fun testDisableFeature_clearFavorites() {
+        controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
+        assertFalse(controller.getFavoriteControls().isEmpty())
+
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, user)
+        controller.settingObserver.onChange(false, ControlsControllerImpl.URI, user)
+        assertTrue(controller.getFavoriteControls().isEmpty())
+    }
+
+    @Test
+    fun testDisableFeature_noChangeForNotCurrentUser() {
+        controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
+        controller.settingObserver.onChange(false, ControlsControllerImpl.URI, otherUser)
+
+        assertTrue(controller.available)
+        assertFalse(controller.getFavoriteControls().isEmpty())
+    }
+
+    @Test
+    fun testCorrectUserSettingOnUserChange() {
+        Settings.Secure.putIntForUser(mContext.contentResolver,
+                ControlsControllerImpl.CONTROLS_AVAILABLE, 0, otherUser)
+
+        val intent = Intent(Intent.ACTION_USER_SWITCHED).apply {
+            putExtra(Intent.EXTRA_USER_HANDLE, otherUser)
+        }
+        val pendingResult = mock(BroadcastReceiver.PendingResult::class.java)
+        `when`(pendingResult.sendingUserId).thenReturn(otherUser)
+        broadcastReceiverCaptor.value.pendingResult = pendingResult
+
+        broadcastReceiverCaptor.value.onReceive(mContext, intent)
+
+        assertFalse(controller.available)
+    }
+
+    @Test
+    fun testCountFavoritesForComponent_singleComponent() {
+        controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
+
+        assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT))
+        assertEquals(0, controller.countFavoritesForComponent(TEST_COMPONENT_2))
+    }
+
+    @Test
+    fun testCountFavoritesForComponent_multipleComponents() {
+        controller.changeFavoriteStatus(TEST_CONTROL_INFO, true)
+        controller.changeFavoriteStatus(TEST_CONTROL_INFO_2, true)
+
+        assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT))
+        assertEquals(1, controller.countFavoritesForComponent(TEST_COMPONENT_2))
+    }
+}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 07abe1a..39c402b 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -272,13 +272,6 @@
 
         mStateReceiver = new StateReceiver();
 
-        mNetdCallback = new NetdCallback();
-        try {
-            mNetd.registerUnsolicitedEventListener(mNetdCallback);
-        } catch (RemoteException e) {
-            mLog.e("Unable to register netd UnsolicitedEventListener");
-        }
-
         final UserManager userManager = (UserManager) mContext.getSystemService(
                 Context.USER_SERVICE);
         mTetheringRestriction = new UserRestrictionActionListener(userManager, this);
@@ -287,6 +280,14 @@
 
         // Load tethering configuration.
         updateConfiguration();
+        // NetdCallback should be registered after updateConfiguration() to ensure
+        // TetheringConfiguration is created.
+        mNetdCallback = new NetdCallback();
+        try {
+            mNetd.registerUnsolicitedEventListener(mNetdCallback);
+        } catch (RemoteException e) {
+            mLog.e("Unable to register netd UnsolicitedEventListener");
+        }
 
         startStateMachineUpdaters(mHandler);
         startTrackDefaultNetwork();
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 2fc9d04..c4e6427 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,6 +16,11 @@
 
 package com.android.server.compat;
 
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.content.Context;
@@ -67,12 +72,14 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, appInfo.uid,
                 ChangeReporter.STATE_LOGGED);
     }
 
     @Override
     public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return;
@@ -82,11 +89,13 @@
 
     @Override
     public void reportChangeByUid(long changeId, int uid) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, uid, ChangeReporter.STATE_LOGGED);
     }
 
     @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeReadAndLogPermission();
         if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
             reportChange(changeId, appInfo.uid,
                     ChangeReporter.STATE_ENABLED);
@@ -99,6 +108,7 @@
 
     @Override
     public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeReadAndLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return true;
@@ -108,6 +118,7 @@
 
     @Override
     public boolean isChangeEnabledByUid(long changeId, int uid) {
+        checkCompatChangeReadAndLogPermission();
         String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
         if (packages == null || packages.length == 0) {
             return true;
@@ -140,6 +151,7 @@
     @Override
     public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
         killPackage(packageName);
     }
@@ -147,11 +159,13 @@
     @Override
     public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
     }
 
     @Override
     public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
         killPackage(packageName);
     }
@@ -159,12 +173,14 @@
     @Override
     public void clearOverridesForTest(String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
     }
 
     @Override
     public boolean clearOverride(long changeId, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         boolean existed = mCompatConfig.removeOverride(changeId, packageName);
         killPackage(packageName);
         return existed;
@@ -172,11 +188,13 @@
 
     @Override
     public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
+        checkCompatChangeReadAndLogPermission();
         return mCompatConfig.getAppConfig(appInfo);
     }
 
     @Override
     public CompatibilityChangeInfo[] listAllChanges() {
+        checkCompatChangeReadPermission();
         return mCompatConfig.dumpChanges();
     }
 
@@ -215,6 +233,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        checkCompatChangeReadAndLogPermission();
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         mCompatConfig.dumpConfig(pw);
     }
@@ -272,4 +291,30 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void checkCompatChangeLogPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot log compat change usage");
+        }
+    }
+
+    private void checkCompatChangeReadPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot read compat change");
+        }
+    }
+
+    private void checkCompatChangeOverridePermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot override compat change");
+        }
+    }
+
+    private void checkCompatChangeReadAndLogPermission() throws SecurityException {
+        checkCompatChangeReadPermission();
+        checkCompatChangeLogPermission();
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 40ea6cf..b98bb08 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -234,12 +234,12 @@
     }
 
     public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
-            String dataAppName, int appId, String seInfo, int targetSdkVersion)
-            throws InstallerException {
+            String dataAppName, int appId, String seInfo, int targetSdkVersion,
+            String fromCodePath) throws InstallerException {
         if (!checkBeforeRemote()) return;
         try {
             mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo,
-                    targetSdkVersion);
+                    targetSdkVersion, fromCodePath);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c14b42d..c8585907 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -150,6 +150,7 @@
 import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
+import android.content.pm.DataLoaderType;
 import android.content.pm.FallbackCategoryProvider;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IDexModuleRegisterCallback;
@@ -1658,7 +1659,8 @@
                         handlePackagePostInstall(parentRes, grantPermissions,
                                 killApp, virtualPreload, grantedPermissions,
                                 whitelistedRestrictedPermissions, didRestore,
-                                args.installSource.installerPackageName, args.observer);
+                                args.installSource.installerPackageName, args.observer,
+                                args.mDataLoaderType);
 
                         // Handle the child packages
                         final int childCount = (parentRes.addedChildPackages != null)
@@ -1668,7 +1670,8 @@
                             handlePackagePostInstall(childRes, grantPermissions,
                                     killApp, virtualPreload, grantedPermissions,
                                     whitelistedRestrictedPermissions, false /*didRestore*/,
-                                    args.installSource.installerPackageName, args.observer);
+                                    args.installSource.installerPackageName, args.observer,
+                                    args.mDataLoaderType);
                         }
 
                         // Log tracing if needed
@@ -1995,7 +1998,7 @@
             boolean killApp, boolean virtualPreload,
             String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
             boolean launchedForRestore, String installerPackage,
-            IPackageInstallObserver2 installObserver) {
+            IPackageInstallObserver2 installObserver, int dataLoaderType) {
         final boolean succeeded = res.returnCode == PackageManager.INSTALL_SUCCEEDED;
         final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null;
 
@@ -2096,11 +2099,14 @@
                 if (update) {
                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
                 }
+                extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
+                // Send to all running apps.
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                         extras, 0 /*flags*/,
                         null /*targetPackage*/, null /*finishedReceiver*/,
                         updateUserIds, instantUserIds);
                 if (installerPackageName != null) {
+                    // Send to the installer, even if it's not running.
                     sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                             extras, 0 /*flags*/,
                             installerPackageName, null /*finishedReceiver*/,
@@ -13978,9 +13984,11 @@
         final int appId;
         final String seinfo;
         final int targetSdkVersion;
+        final String fromCodePath;
 
         public MoveInfo(int moveId, String fromUuid, String toUuid, String packageName,
-                String dataAppName, int appId, String seinfo, int targetSdkVersion) {
+                String dataAppName, int appId, String seinfo, int targetSdkVersion,
+                String fromCodePath) {
             this.moveId = moveId;
             this.fromUuid = fromUuid;
             this.toUuid = toUuid;
@@ -13989,6 +13997,7 @@
             this.appId = appId;
             this.seinfo = seinfo;
             this.targetSdkVersion = targetSdkVersion;
+            this.fromCodePath = fromCodePath;
         }
     }
 
@@ -14114,13 +14123,14 @@
         MultiPackageInstallParams mParentInstallParams;
         final long requiredInstalledVersionCode;
         final boolean forceQueryableOverride;
+        final int mDataLoaderType;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, InstallSource installSource, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                 String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
                 SigningDetails signingDetails, int installReason,
-                long requiredInstalledVersionCode) {
+                long requiredInstalledVersionCode, int dataLoaderType) {
             super(user);
             this.origin = origin;
             this.move = move;
@@ -14136,40 +14146,42 @@
             this.installReason = installReason;
             this.requiredInstalledVersionCode = requiredInstalledVersionCode;
             this.forceQueryableOverride = false;
+            this.mDataLoaderType = dataLoaderType;
         }
 
         InstallParams(ActiveInstallSession activeInstallSession) {
             super(activeInstallSession.getUser());
+            final PackageInstaller.SessionParams sessionParams =
+                    activeInstallSession.getSessionParams();
             if (DEBUG_INSTANT) {
-                if ((activeInstallSession.getSessionParams().installFlags
+                if ((sessionParams.installFlags
                         & PackageManager.INSTALL_INSTANT_APP) != 0) {
                     Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
                 }
             }
             verificationInfo = new VerificationInfo(
-                    activeInstallSession.getSessionParams().originatingUri,
-                    activeInstallSession.getSessionParams().referrerUri,
-                    activeInstallSession.getSessionParams().originatingUid,
+                    sessionParams.originatingUri,
+                    sessionParams.referrerUri,
+                    sessionParams.originatingUid,
                     activeInstallSession.getInstallerUid());
             origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
             move = null;
             installReason = fixUpInstallReason(
                     activeInstallSession.getInstallSource().installerPackageName,
                     activeInstallSession.getInstallerUid(),
-                    activeInstallSession.getSessionParams().installReason);
+                    sessionParams.installReason);
             observer = activeInstallSession.getObserver();
-            installFlags = activeInstallSession.getSessionParams().installFlags;
+            installFlags = sessionParams.installFlags;
             installSource = activeInstallSession.getInstallSource();
-            volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
-            packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
-            grantedRuntimePermissions = activeInstallSession.getSessionParams()
-                    .grantedRuntimePermissions;
-            whitelistedRestrictedPermissions = activeInstallSession.getSessionParams()
-                    .whitelistedRestrictedPermissions;
+            volumeUuid = sessionParams.volumeUuid;
+            packageAbiOverride = sessionParams.abiOverride;
+            grantedRuntimePermissions = sessionParams.grantedRuntimePermissions;
+            whitelistedRestrictedPermissions = sessionParams.whitelistedRestrictedPermissions;
             signingDetails = activeInstallSession.getSigningDetails();
-            requiredInstalledVersionCode = activeInstallSession.getSessionParams()
-                    .requiredInstalledVersionCode;
-            forceQueryableOverride = activeInstallSession.getSessionParams().forceQueryableOverride;
+            requiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
+            forceQueryableOverride = sessionParams.forceQueryableOverride;
+            mDataLoaderType = (sessionParams.dataLoaderParams != null)
+                    ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
         }
 
         @Override
@@ -14772,6 +14784,7 @@
         final int installReason;
         final boolean forceQueryableOverride;
         @Nullable final MultiPackageInstallParams mMultiPackageInstallParams;
+        final int mDataLoaderType;
 
         // The list of instruction sets supported by this app. This is currently
         // only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -14785,7 +14798,7 @@
                 List<String> whitelistedRestrictedPermissions,
                 String traceMethod, int traceCookie, SigningDetails signingDetails,
                 int installReason, boolean forceQueryableOverride,
-                MultiPackageInstallParams multiPackageInstallParams) {
+                MultiPackageInstallParams multiPackageInstallParams, int dataLoaderType) {
             this.origin = origin;
             this.move = move;
             this.installFlags = installFlags;
@@ -14803,6 +14816,7 @@
             this.installReason = installReason;
             this.forceQueryableOverride = forceQueryableOverride;
             this.mMultiPackageInstallParams = multiPackageInstallParams;
+            this.mDataLoaderType = dataLoaderType;
         }
 
         /** New install */
@@ -14812,7 +14826,8 @@
                     params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
                     params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason, params.forceQueryableOverride, params.mParentInstallParams);
+                    params.installReason, params.forceQueryableOverride,
+                    params.mParentInstallParams, params.mDataLoaderType);
         }
 
         abstract int copyApk();
@@ -14903,7 +14918,8 @@
             super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
                     null, null, instructionSets, null, null, null, null, 0,
                     PackageParser.SigningDetails.UNKNOWN,
-                    PackageManager.INSTALL_REASON_UNKNOWN, false, null /* parent */);
+                    PackageManager.INSTALL_REASON_UNKNOWN, false, null /* parent */,
+                    DataLoaderType.NONE);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
         }
@@ -14983,9 +14999,7 @@
             try {
                 makeDirRecursive(afterCodeFile.getParentFile(), 0775);
                 if (onIncremental) {
-                    // TODO(b/147371381): fix incremental installation
-                    mIncrementalManager.rename(beforeCodeFile.getAbsolutePath(),
-                            afterCodeFile.getAbsolutePath());
+                    mIncrementalManager.renameCodePath(beforeCodeFile, afterCodeFile);
                 } else {
                     Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
                 }
@@ -15104,7 +15118,8 @@
             synchronized (mInstaller) {
                 try {
                     mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
-                            move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion);
+                            move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion,
+                            move.fromCodePath);
                 } catch (InstallerException e) {
                     Slog.w(TAG, "Failed to move app", e);
                     return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -22054,6 +22069,7 @@
         final PackageFreezer freezer;
         final int[] installedUserIds;
         final boolean isCurrentLocationExternal;
+        final String fromCodePath;
 
         // reader
         synchronized (mLock) {
@@ -22110,6 +22126,7 @@
             targetSdkVersion = pkg.getTargetSdkVersion();
             freezer = freezePackage(packageName, "movePackageInternal");
             installedUserIds = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
+            fromCodePath = pkg.getCodePath();
         }
 
         final Bundle extras = new Bundle();
@@ -22238,7 +22255,7 @@
 
             final String dataAppName = codeFile.getName();
             move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName,
-                    dataAppName, appId, seinfo, targetSdkVersion);
+                    dataAppName, appId, seinfo, targetSdkVersion, fromCodePath);
         } else {
             move = null;
         }
@@ -22251,7 +22268,8 @@
                 installSource, volumeUuid, null /*verificationInfo*/, user,
                 packageAbiOverride, null /*grantedPermissions*/,
                 null /*whitelistedRestrictedPermissions*/, PackageParser.SigningDetails.UNKNOWN,
-                PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST);
+                PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST,
+                DataLoaderType.NONE);
         params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 6daf516..6eba59a 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -402,7 +402,7 @@
         public String getStatus() {
             return mContext.getString(
                     com.android.internal.R.string.bugreport_status,
-                    Build.VERSION.RELEASE,
+                    Build.VERSION.RELEASE_OR_CODENAME,
                     Build.ID);
         }
     }
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 96f1219..5c79f6e 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -2480,7 +2480,7 @@
                 .writeString(Build.BRAND)
                 .writeString(Build.PRODUCT)
                 .writeString(Build.DEVICE)
-                .writeString(Build.VERSION.RELEASE)
+                .writeString(Build.VERSION.RELEASE_OR_CODENAME)
                 .writeString(Build.ID)
                 .writeString(Build.VERSION.INCREMENTAL)
                 .writeString(Build.TYPE)
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 75d87ed..f35ba9e 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -386,6 +386,8 @@
         } else {
             callingPid = callingUid = -1;
         }
+        final int filterCallingUid = ActivityStarter.computeResolveFilterUid(
+                callingUid, realCallingUid, UserHandle.USER_NULL);
         final SparseArray<String> startingUidPkgs = new SparseArray<>();
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -408,9 +410,7 @@
 
                 // Collect information about the target of the Intent.
                 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i],
-                        0 /* startFlags */, null /* profilerInfo */, userId,
-                        ActivityStarter.computeResolveFilterUid(
-                                callingUid, realCallingUid, UserHandle.USER_NULL));
+                        0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid);
                 aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
 
                 if (aInfo != null) {
@@ -457,6 +457,7 @@
                 Slog.wtf(TAG, sb.toString());
             }
 
+            final IBinder sourceResultTo = resultTo;
             final ActivityRecord[] outActivity = new ActivityRecord[1];
             // Lock the loop to ensure the activities launched in a sequence.
             synchronized (mService.mGlobalLock) {
@@ -470,7 +471,18 @@
                         }
                         return startResult;
                     }
-                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
+                    final ActivityRecord started = outActivity[0];
+                    if (started != null && started.getUid() == filterCallingUid) {
+                        // Only the started activity which has the same uid as the source caller can
+                        // be the caller of next activity.
+                        resultTo = started.appToken;
+                    } else {
+                        resultTo = sourceResultTo;
+                        // Different apps not adjacent to the caller are forced to be new task.
+                        if (i < starters.length - 1) {
+                            starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        }
+                    }
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 9e3292b..c7270f2 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2493,7 +2493,6 @@
         return this;
     }
 
-    @VisibleForTesting
     Intent getIntent() {
         return mRequest.intent;
     }
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 0e24b03..44eb828 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -17,6 +17,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.frameworks.mockingservicestests">
 
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
     <uses-permission android:name="android.permission.HARDWARE_TEST"/>
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index d2ddff3..1212f20 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -65,6 +65,8 @@
     <uses-permission android:name="android.permission.WATCH_APPOPS" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SUSPEND_APPS"/>
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 180deb5..dab0a5f 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -28,6 +28,8 @@
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
     <uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index 5e9ef8e..74dfde8 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -18,14 +18,11 @@
     name: "PlatformCompatGating",
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
-    certificate: "platform",
-    libs: [
-        "android.test.runner",
-        "android.test.base",
-    ],
     static_libs: [
         "junit",
-        "android-support-test",
+        "androidx.test.runner",
+        "androidx.test.core",
+        "androidx.test.ext.junit",
         "mockito-target-minus-junit4",
         "truth-prebuilt",
         "platform-compat-test-rules"
diff --git a/tests/PlatformCompatGating/AndroidManifest.xml b/tests/PlatformCompatGating/AndroidManifest.xml
index 7f14b83..c24dc31 100644
--- a/tests/PlatformCompatGating/AndroidManifest.xml
+++ b/tests/PlatformCompatGating/AndroidManifest.xml
@@ -6,6 +6,6 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.tests.gating"/>
 </manifest>
diff --git a/tests/PlatformCompatGating/AndroidTest.xml b/tests/PlatformCompatGating/AndroidTest.xml
index c626848..0c7485b 100644
--- a/tests/PlatformCompatGating/AndroidTest.xml
+++ b/tests/PlatformCompatGating/AndroidTest.xml
@@ -24,7 +24,6 @@
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest">
         <option name="package" value="com.android.tests.gating"/>
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java
index dc317f19..c1ce0e9 100644
--- a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java
+++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatGatingTest.java
@@ -18,8 +18,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.compat.testing.PlatformCompatChangeRule;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.compat.testing.DummyApi;
 
@@ -81,14 +82,14 @@
     @Test
     @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
     public void testDummyGatingPositiveSystemServer() {
-        assertThat(
-                DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isTrue();
+        assertThat(DummyApi.dummySystemServer(
+                InstrumentationRegistry.getInstrumentation().getTargetContext())).isTrue();
     }
 
     @Test
     @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
     public void testDummyGatingNegativeSystemServer() {
-        assertThat(
-                DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isFalse();
+        assertThat(DummyApi.dummySystemServer(
+                InstrumentationRegistry.getInstrumentation().getTargetContext())).isFalse();
     }
 }
diff --git a/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java
new file mode 100644
index 0000000..9b9e581
--- /dev/null
+++ b/tests/PlatformCompatGating/src/com/android/tests/gating/PlatformCompatPermissionsTest.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2020 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.tests.gating;
+
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.compat.Compatibility.ChangeConfig;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.ServiceManager;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.compat.CompatibilityChangeConfig;
+import com.android.internal.compat.IPlatformCompat;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public final class PlatformCompatPermissionsTest {
+
+    // private Context mContext;
+    private IPlatformCompat mPlatformCompat;
+
+    @Rule
+    public final ExpectedException thrown = ExpectedException.none();
+    private Context mContext;
+    private UiAutomation mUiAutomation;
+    private PackageManager mPackageManager;
+
+    @Before
+    public void setUp() {
+        // mContext;
+        mPlatformCompat = IPlatformCompat.Stub
+            .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        mUiAutomation = instrumentation.getUiAutomation();
+        mContext = instrumentation.getTargetContext();
+
+        mPackageManager = mContext.getPackageManager();
+    }
+
+    @After
+    public void tearDown() {
+
+        mUiAutomation.dropShellPermissionIdentity();
+    }
+
+    @Test
+    public void reportChange_noLogCompatChangePermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0));
+    }
+
+    @Test
+    public void reportChange_logCompatChangePermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.reportChange(1, mPackageManager.getApplicationInfo(packageName, 0));
+    }
+
+    @Test
+    public void reportChangeByPackageName_noLogCompatChangePermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.reportChangeByPackageName(1, packageName, 0);
+    }
+
+    @Test
+    public void reportChangeByPackageName_logCompatChangePermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.reportChangeByPackageName(1, packageName, 0);
+    }
+
+    @Test
+    public void reportChangeByUid_noLogCompatChangePermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.reportChangeByUid(1, Process.myUid());
+    }
+
+    @Test
+    public void reportChangeByUid_logCompatChangePermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(LOG_COMPAT_CHANGE);
+
+        mPlatformCompat.reportChangeByUid(1, Process.myUid());
+    }
+
+    @Test
+    public void isChangeEnabled_noReadCompatConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
+    }
+
+    @Test
+    public void isChangeEnabled_noLogCompatChangeConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
+    }
+
+    @Test
+    public void isChangeEnabled_readAndLogCompatChangeConfigPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabled(1, mPackageManager.getApplicationInfo(packageName, 0));
+    }
+
+    @Test
+    public void isChangeEnabledByPackageName_noReadCompatConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
+    }
+
+    @Test
+    public void isChangeEnabledByPackageName_noLogompatConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
+    }
+
+    @Test
+    public void isChangeEnabledByPackageName_readAndLogCompatChangeConfigPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
+        final String packageName = mContext.getPackageName();
+
+        mPlatformCompat.isChangeEnabledByPackageName(1, packageName, 0);
+    }
+
+    @Test
+    public void isChangeEnabledByUid_noReadCompatConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
+    }
+
+    @Test
+    public void isChangeEnabledByUid_noLogCompatChangePermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
+
+        mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
+    }
+
+    @Test
+    public void isChangeEnabledByUid_readAndLogCompatChangeConfigPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG, LOG_COMPAT_CHANGE);
+
+        mPlatformCompat.isChangeEnabledByUid(1, Process.myUid());
+    }
+
+    @Test
+    public void setOverrides_noOverridesPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        Set<Long> enabled = new HashSet<>();
+        Set<Long> disabled = new HashSet<>();
+        ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
+        CompatibilityChangeConfig compatibilityChangeConfig =
+                new CompatibilityChangeConfig(changeConfig);
+
+        mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar");
+    }
+    @Test
+    public void setOverrides_overridesPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
+        Set<Long> enabled = new HashSet<>();
+        Set<Long> disabled = new HashSet<>();
+        ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
+        CompatibilityChangeConfig compatibilityChangeConfig =
+                new CompatibilityChangeConfig(changeConfig);
+
+        mPlatformCompat.setOverrides(compatibilityChangeConfig, "foo.bar");
+    }
+
+    @Test
+    public void setOverridesForTest_noOverridesPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+        Set<Long> enabled = new HashSet<>();
+        Set<Long> disabled = new HashSet<>();
+        ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
+        CompatibilityChangeConfig compatibilityChangeConfig =
+                new CompatibilityChangeConfig(changeConfig);
+
+        mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar");
+    }
+    @Test
+    public void setOverridesForTest_overridesPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
+        Set<Long> enabled = new HashSet<>();
+        Set<Long> disabled = new HashSet<>();
+        ChangeConfig changeConfig = new ChangeConfig(enabled, disabled);
+        CompatibilityChangeConfig compatibilityChangeConfig =
+                new CompatibilityChangeConfig(changeConfig);
+
+        mPlatformCompat.setOverridesForTest(compatibilityChangeConfig, "foo.bar");
+    }
+
+    @Test
+    public void clearOverrides_noOverridesPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.clearOverrides("foo.bar");
+    }
+    @Test
+    public void clearOverrides_overridesPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
+
+        mPlatformCompat.clearOverrides("foo.bar");
+    }
+
+    @Test
+    public void clearOverridesForTest_noOverridesPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.clearOverridesForTest("foo.bar");
+    }
+    @Test
+    public void clearOverridesForTest_overridesPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
+
+        mPlatformCompat.clearOverridesForTest("foo.bar");
+    }
+
+    @Test
+    public void clearOverride_noOverridesPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.clearOverride(1, "foo.bar");
+    }
+    @Test
+    public void clearOverride_overridesPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(OVERRIDE_COMPAT_CHANGE_CONFIG);
+
+        mPlatformCompat.clearOverride(1, "foo.bar");
+    }
+
+    @Test
+    public void listAllChanges_noReadCompatConfigPermission_throwsSecurityException()
+            throws Throwable {
+        thrown.expect(SecurityException.class);
+
+        mPlatformCompat.listAllChanges();
+    }
+    @Test
+    public void listAllChanges_readCompatConfigPermission_noThrow()
+            throws Throwable {
+        mUiAutomation.adoptShellPermissionIdentity(READ_COMPAT_CHANGE_CONFIG);
+
+        mPlatformCompat.listAllChanges();
+    }
+}
diff --git a/tests/PlatformCompatGating/test-rules/Android.bp b/tests/PlatformCompatGating/test-rules/Android.bp
index 8211ef5..10fa2dc 100644
--- a/tests/PlatformCompatGating/test-rules/Android.bp
+++ b/tests/PlatformCompatGating/test-rules/Android.bp
@@ -19,7 +19,7 @@
     srcs: ["src/**/*.java"],
     static_libs: [
         "junit",
-        "android-support-test",
+        "androidx.test.core",
         "truth-prebuilt",
         "core-compat-test-rules"
     ],
diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
index 932ec64..d6846fa 100644
--- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
+++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
@@ -16,13 +16,17 @@
 
 package android.compat.testing;
 
+import android.Manifest;
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.compat.Compatibility;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.support.test.InstrumentationRegistry;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
 
 import com.android.internal.compat.CompatibilityChangeConfig;
 import com.android.internal.compat.IPlatformCompat;
@@ -83,12 +87,17 @@
         @Override
         public void evaluate() throws Throwable {
             Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+            UiAutomation uiAutomation = instrumentation.getUiAutomation();
             String packageName = instrumentation.getTargetContext().getPackageName();
             IPlatformCompat platformCompat = IPlatformCompat.Stub
                     .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
             if (platformCompat == null) {
                 throw new IllegalStateException("Could not get IPlatformCompat service!");
             }
+            uiAutomation.adoptShellPermissionIdentity(
+                    Manifest.permission.LOG_COMPAT_CHANGE,
+                    Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG,
+                    Manifest.permission.READ_COMPAT_CHANGE_CONFIG);
             Compatibility.setOverrides(mConfig);
             try {
                 platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
@@ -101,6 +110,7 @@
             } catch (RemoteException e) {
                 throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
             } finally {
+                uiAutomation.dropShellPermissionIdentity();
                 Compatibility.clearOverrides();
             }
         }
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index d3958a6..a251c05 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -30,7 +30,7 @@
         "utils.cpp",
     ],
     cflags: [
-        "-DSTATS_SCHEMA_LEGACY",
+        //"-DSTATS_SCHEMA_LEGACY",
         "-Wall",
         "-Werror",
     ],