Merge "Migrate android_uiautomator generation to Soong." into pi-dev-plus-aosp
diff --git a/CleanSpec.mk b/CleanSpec.mk
index e728897..2e949c5 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -243,6 +243,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/core/java/android/os/storage/*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/host/common/obj/JAVA_LIBRARIES/platformprotos_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/statsdprotolite_intermediates)
 # ******************************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
 # ******************************************************************
diff --git a/api/test-current.txt b/api/test-current.txt
index 9403b49..dd88856 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -604,6 +604,10 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
+  public final class PowerManager {
+    method public void nap(long);
+  }
+
   public class Process {
     method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
   }
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 45d6281..5604973 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -70,6 +70,13 @@
     return WriteFully(fd, buf, p - buf) ? NO_ERROR : -errno;
 }
 
+static void write_section_stats(IncidentMetadata::SectionStats* stats, const FdBuffer& buffer) {
+    stats->set_dump_size_bytes(buffer.data().size());
+    stats->set_dump_duration_ms(buffer.durationMs());
+    stats->set_timed_out(buffer.timedOut());
+    stats->set_is_truncated(buffer.truncated());
+}
+
 // Reads data from FdBuffer and writes it to the requests file descriptor.
 static status_t write_report_requests(const int id, const FdBuffer& buffer,
                                       ReportRequestSet* requests) {
@@ -77,12 +84,6 @@
     EncodedBuffer::iterator data = buffer.data();
     PrivacyBuffer privacyBuffer(get_privacy_of_section(id), data);
     int writeable = 0;
-    IncidentMetadata::SectionStats* stats = requests->sectionStats(id);
-
-    stats->set_dump_size_bytes(data.size());
-    stats->set_dump_duration_ms(buffer.durationMs());
-    stats->set_timed_out(buffer.timedOut());
-    stats->set_is_truncated(buffer.truncated());
 
     // The streaming ones, group requests by spec in order to save unnecessary strip operations
     map<PrivacySpec, vector<sp<ReportRequest>>> requestsBySpec;
@@ -140,7 +141,8 @@
         writeable++;
         VLOG("Section %d flushed %zu bytes to dropbox %d with spec %d", id, privacyBuffer.size(),
              requests->mainFd(), spec.dest);
-        stats->set_report_size_bytes(privacyBuffer.size());
+        // Reports bytes of the section uploaded via dropbox after filtering.
+        requests->sectionStats(id)->set_report_size_bytes(privacyBuffer.size());
     }
 
 DONE:
@@ -270,7 +272,7 @@
     status_t readStatus = buffer.readProcessedDataInStream(fd.get(), std::move(p2cPipe.writeFd()),
                                                            std::move(c2pPipe.readFd()),
                                                            this->timeoutMs, mIsSysfs);
-
+    write_section_stats(requests->sectionStats(this->id), buffer);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s",
               this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
@@ -363,7 +365,7 @@
     status_t readStatus = buffer.readProcessedDataInStream(
             fd.get(), std::move(p2cPipe.writeFd()), std::move(c2pPipe.readFd()), this->timeoutMs,
             isSysfs(mFilenames[index]));
-
+    write_section_stats(requests->sectionStats(this->id), buffer);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("GZipSection '%s' failed to read data from gzip: %s, timedout: %s",
               this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
@@ -499,7 +501,7 @@
             }
         }
     }
-
+    write_section_stats(requests->sectionStats(this->id), buffer);
     if (timedOut || buffer.timedOut()) {
         ALOGW("WorkerThreadSection '%s' timed out", this->name.string());
         return NO_ERROR;
@@ -580,6 +582,7 @@
 
     cmdPipe.writeFd().reset();
     status_t readStatus = buffer.read(ihPipe.readFd().get(), this->timeoutMs);
+    write_section_stats(requests->sectionStats(this->id), buffer);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
         ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s",
               this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
@@ -927,4 +930,4 @@
 
 }  // namespace incidentd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 9f92353..33f5206 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -146,6 +146,7 @@
 TEST_F(SectionTest, FileSectionTimeout) {
     FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
     ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
+    ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
 }
 
 TEST_F(SectionTest, GZipSection) {
@@ -204,12 +205,14 @@
 TEST_F(SectionTest, CommandSectionCommandTimeout) {
     CommandSection cs(NOOP_PARSER, QUICK_TIMEOUT_MS, "/system/bin/yes", NULL);
     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+    ASSERT_TRUE(requests.sectionStats(NOOP_PARSER)->timed_out());
 }
 
 TEST_F(SectionTest, CommandSectionIncidentHelperTimeout) {
     CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "/system/bin/echo", "about", NULL);
     requests.setMainFd(STDOUT_FILENO);
     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+    ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
 }
 
 TEST_F(SectionTest, CommandSectionBadCommand) {
@@ -221,6 +224,7 @@
     CommandSection cs(TIMEOUT_PARSER, QUICK_TIMEOUT_MS, "nonexistcommand", "-opt", NULL);
     // timeout will return first
     ASSERT_EQ(NO_ERROR, cs.Execute(&requests));
+    ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
 }
 
 TEST_F(SectionTest, LogSectionBinary) {
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index e26806b..d025337 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -27,8 +27,10 @@
 #include "subscriber/SubscriberReporter.h"
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/PermissionController.h>
 #include <dirent.h>
 #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h>
 #include <private/android_filesystem_config.h>
@@ -42,13 +44,83 @@
 
 using namespace android;
 
+using android::base::StringPrintf;
+
 namespace android {
 namespace os {
 namespace statsd {
 
 constexpr const char* kPermissionDump = "android.permission.DUMP";
+constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS";
+
+constexpr const char* kOpUsage = "android:get_usage_stats";
+
 #define STATS_SERVICE_DIR "/data/misc/stats-service"
 
+static binder::Status ok() {
+    return binder::Status::ok();
+}
+
+static binder::Status exception(uint32_t code, const std::string& msg) {
+    ALOGE("%s (%d)", msg.c_str(), code);
+    return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
+}
+
+binder::Status checkUid(uid_t expectedUid) {
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (uid == expectedUid || uid == AID_ROOT) {
+        return ok();
+    } else {
+        return exception(binder::Status::EX_SECURITY,
+                StringPrintf("UID %d is not expected UID %d", uid, expectedUid));
+    }
+}
+
+binder::Status checkDumpAndUsageStats(const String16& packageName) {
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+
+    // Root, system, and shell always have access
+    if (uid == AID_ROOT || uid == AID_SYSTEM || uid == AID_SHELL) {
+        return ok();
+    }
+
+    // Caller must be granted these permissions
+    if (!checkCallingPermission(String16(kPermissionDump))) {
+        return exception(binder::Status::EX_SECURITY,
+                StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionDump));
+    }
+    if (!checkCallingPermission(String16(kPermissionUsage))) {
+        return exception(binder::Status::EX_SECURITY,
+                StringPrintf("UID %d / PID %d lacks permission %s", uid, pid, kPermissionUsage));
+    }
+
+    // Caller must also have usage stats op granted
+    PermissionController pc;
+    switch (pc.noteOp(String16(kOpUsage), uid, packageName)) {
+        case PermissionController::MODE_ALLOWED:
+        case PermissionController::MODE_DEFAULT:
+            return ok();
+        default:
+            return exception(binder::Status::EX_SECURITY,
+                    StringPrintf("UID %d / PID %d lacks app-op %s", uid, pid, kOpUsage));
+    }
+}
+
+#define ENFORCE_UID(uid) {                                        \
+    binder::Status status = checkUid((uid));                      \
+    if (!status.isOk()) {                                         \
+        return status;                                            \
+    }                                                             \
+}
+
+#define ENFORCE_DUMP_AND_USAGE_STATS(packageName) {               \
+    binder::Status status = checkDumpAndUsageStats(packageName);  \
+    if (!status.isOk()) {                                         \
+        return status;                                            \
+    }                                                             \
+}
+
 StatsService::StatsService(const sp<Looper>& handlerLooper)
     : mAnomalyAlarmMonitor(new AlarmMonitor(MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
        [](const sp<IStatsCompanionService>& sc, int64_t timeMillis) {
@@ -172,6 +244,9 @@
  * Write debugging data about statsd.
  */
 status_t StatsService::dump(int fd, const Vector<String16>& args) {
+    if (!checkCallingPermission(String16(kPermissionDump))) {
+        return PERMISSION_DENIED;
+    }
     FILE* out = fdopen(fd, "w");
     if (out == NULL) {
         return NO_MEMORY;  // the fd is already open
@@ -212,7 +287,10 @@
  * Implementation of the adb shell cmd stats command.
  */
 status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) {
-    // TODO: Permission check
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    if (uid != AID_ROOT && uid != AID_SHELL) {
+        return PERMISSION_DENIED;
+    }
 
     const int argCount = args.size();
     if (argCount >= 1) {
@@ -661,13 +739,9 @@
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
                                       const vector<String16>& app) {
+    ENFORCE_UID(AID_SYSTEM);
+
     VLOG("StatsService::informAllUidData was called");
-
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call informAllUidData");
-    }
-
     mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
     VLOG("StatsService::informAllUidData succeeded");
 
@@ -675,36 +749,26 @@
 }
 
 Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
-    VLOG("StatsService::informOnePackage was called");
+    ENFORCE_UID(AID_SYSTEM);
 
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call informOnePackage");
-    }
+    VLOG("StatsService::informOnePackage was called");
     mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
     return Status::ok();
 }
 
 Status StatsService::informOnePackageRemoved(const String16& app, int32_t uid) {
-    VLOG("StatsService::informOnePackageRemoved was called");
+    ENFORCE_UID(AID_SYSTEM);
 
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call informOnePackageRemoved");
-    }
+    VLOG("StatsService::informOnePackageRemoved was called");
     mUidMap->removeApp(getElapsedRealtimeNs(), app, uid);
     mConfigManager->RemoveConfigs(uid);
     return Status::ok();
 }
 
 Status StatsService::informAnomalyAlarmFired() {
+    ENFORCE_UID(AID_SYSTEM);
+
     VLOG("StatsService::informAnomalyAlarmFired was called");
-
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call informAnomalyAlarmFired");
-    }
-
     int64_t currentTimeSec = getElapsedRealtimeSec();
     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
             mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
@@ -718,14 +782,9 @@
 }
 
 Status StatsService::informAlarmForSubscriberTriggeringFired() {
+    ENFORCE_UID(AID_SYSTEM);
+
     VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
-
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(
-                Status::EX_SECURITY,
-                "Only system uid can call informAlarmForSubscriberTriggeringFired");
-    }
-
     int64_t currentTimeSec = getElapsedRealtimeSec();
     std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
             mPeriodicAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
@@ -739,44 +798,28 @@
 }
 
 Status StatsService::informPollAlarmFired() {
+    ENFORCE_UID(AID_SYSTEM);
+
     VLOG("StatsService::informPollAlarmFired was called");
-
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call informPollAlarmFired");
-    }
-
     mProcessor->informPullAlarmFired(getElapsedRealtimeNs());
-
     VLOG("StatsService::informPollAlarmFired succeeded");
-
     return Status::ok();
 }
 
 Status StatsService::systemRunning() {
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call systemRunning");
-    }
+    ENFORCE_UID(AID_SYSTEM);
 
     // When system_server is up and running, schedule the dropbox task to run.
     VLOG("StatsService::systemRunning");
-
     sayHiToStatsCompanion();
-
     return Status::ok();
 }
 
 Status StatsService::writeDataToDisk() {
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call systemRunning");
-    }
+    ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::writeDataToDisk");
-
     mProcessor->WriteDataToDisk();
-
     return Status::ok();
 }
 
@@ -791,13 +834,9 @@
 }
 
 Status StatsService::statsCompanionReady() {
+    ENFORCE_UID(AID_SYSTEM);
+
     VLOG("StatsService::statsCompanionReady was called");
-
-    if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
-        return Status::fromExceptionCode(Status::EX_SECURITY,
-                                         "Only system uid can call statsCompanionReady");
-    }
-
     sp<IStatsCompanionService> statsCompanion = getStatsCompanionService();
     if (statsCompanion == nullptr) {
         return Status::fromExceptionCode(
@@ -821,33 +860,31 @@
     mProcessor->OnLogEvent(event, reconnectionStarts);
 }
 
-Status StatsService::getData(int64_t key, vector<uint8_t>* output) {
+Status StatsService::getData(int64_t key, const String16& packageName, vector<uint8_t>* output) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
     ConfigKey configKey(ipc->getCallingUid(), key);
     mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
                              false /* include_current_bucket*/, output);
     return Status::ok();
 }
 
-Status StatsService::getMetadata(vector<uint8_t>* output) {
+Status StatsService::getMetadata(const String16& packageName, vector<uint8_t>* output) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     VLOG("StatsService::getMetadata with Pid %i, Uid %i", ipc->getCallingPid(),
          ipc->getCallingUid());
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
     StatsdStats::getInstance().dumpStats(output, false); // Don't reset the counters.
     return Status::ok();
 }
 
-Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config) {
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
+Status StatsService::addConfiguration(int64_t key, const vector <uint8_t>& config,
+                                      const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     if (addConfigurationChecked(ipc->getCallingUid(), key, config)) {
         return Status::ok();
@@ -870,30 +907,29 @@
     return true;
 }
 
-Status StatsService::removeDataFetchOperation(int64_t key) {
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
+Status StatsService::removeDataFetchOperation(int64_t key, const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), key);
     mConfigManager->RemoveConfigReceiver(configKey);
     return Status::ok();
 }
 
-Status StatsService::setDataFetchOperation(int64_t key, const sp<android::IBinder>& intentSender) {
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
+Status StatsService::setDataFetchOperation(int64_t key,
+                                           const sp<android::IBinder>& intentSender,
+                                           const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), key);
     mConfigManager->SetConfigReceiver(configKey, intentSender);
     return Status::ok();
 }
 
-Status StatsService::removeConfiguration(int64_t key) {
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
+Status StatsService::removeConfiguration(int64_t key, const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), key);
     mConfigManager->RemoveConfig(configKey);
@@ -903,11 +939,11 @@
 
 Status StatsService::setBroadcastSubscriber(int64_t configId,
                                             int64_t subscriberId,
-                                            const sp<android::IBinder>& intentSender) {
+                                            const sp<android::IBinder>& intentSender,
+                                            const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     VLOG("StatsService::setBroadcastSubscriber called.");
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), configId);
     SubscriberReporter::getInstance()
@@ -916,11 +952,11 @@
 }
 
 Status StatsService::unsetBroadcastSubscriber(int64_t configId,
-                                              int64_t subscriberId) {
+                                              int64_t subscriberId,
+                                              const String16& packageName) {
+    ENFORCE_DUMP_AND_USAGE_STATS(packageName);
+
     VLOG("StatsService::unsetBroadcastSubscriber called.");
-    if (!checkCallingPermission(String16(kPermissionDump))) {
-        return Status::fromExceptionCode(binder::Status::EX_SECURITY);
-    }
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), configId);
     SubscriberReporter::getInstance()
@@ -928,7 +964,6 @@
     return Status::ok();
 }
 
-
 void StatsService::binderDied(const wp <IBinder>& who) {
     ALOGW("statscompanion service died");
     mProcessor->WriteDataToDisk();
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index d502796..774a3e9 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -81,36 +81,44 @@
     /**
      * Binder call for clients to request data for this configuration key.
      */
-    virtual Status getData(int64_t key, vector<uint8_t>* output) override;
+    virtual Status getData(int64_t key,
+                           const String16& packageName,
+                           vector<uint8_t>* output) override;
 
 
     /**
      * Binder call for clients to get metadata across all configs in statsd.
      */
-    virtual Status getMetadata(vector<uint8_t>* output) override;
+    virtual Status getMetadata(const String16& packageName,
+                               vector<uint8_t>* output) override;
 
 
     /**
      * Binder call to let clients send a configuration and indicate they're interested when they
      * should requestData for this configuration.
      */
-    virtual Status addConfiguration(int64_t key, const vector<uint8_t>& config) override;
+    virtual Status addConfiguration(int64_t key,
+                                    const vector<uint8_t>& config,
+                                    const String16& packageName) override;
 
     /**
      * Binder call to let clients register the data fetch operation for a configuration.
      */
     virtual Status setDataFetchOperation(int64_t key,
-                                         const sp<android::IBinder>& intentSender) override;
+                                         const sp<android::IBinder>& intentSender,
+                                         const String16& packageName) override;
 
     /**
      * Binder call to remove the data fetch operation for the specified config key.
      */
-    virtual Status removeDataFetchOperation(int64_t key) override;
+    virtual Status removeDataFetchOperation(int64_t key,
+                                            const String16& packageName) override;
 
     /**
      * Binder call to allow clients to remove the specified configuration.
      */
-    virtual Status removeConfiguration(int64_t key) override;
+    virtual Status removeConfiguration(int64_t key,
+                                       const String16& packageName) override;
 
     /**
      * Binder call to associate the given config's subscriberId with the given intentSender.
@@ -118,12 +126,15 @@
      */
     virtual Status setBroadcastSubscriber(int64_t configId,
                                           int64_t subscriberId,
-                                          const sp<android::IBinder>& intentSender) override;
+                                          const sp<android::IBinder>& intentSender,
+                                          const String16& packageName) override;
 
     /**
      * Binder call to unassociate the given config's subscriberId with any intentSender.
      */
-    virtual Status unsetBroadcastSubscriber(int64_t configId, int64_t subscriberId) override;
+    virtual Status unsetBroadcastSubscriber(int64_t configId,
+                                            int64_t subscriberId,
+                                            const String16& packageName) override;
 
     /** Inform statsCompanion that statsd is ready. */
     virtual void sayHiToStatsCompanion();
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 5499ee3..af07f6b 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -27,6 +27,7 @@
 
 #ifdef __ANDROID__
 
+const string kAndroid = "android";
 const string kApp1 = "app1.sharing.1";
 const int kConfigKey = 789130123;  // Randomly chosen to avoid collisions with existing configs.
 
@@ -35,12 +36,12 @@
     config.SerializeToString(&str);
     std::vector<uint8_t> configAsVec(str.begin(), str.end());
     bool success;
-    service.addConfiguration(kConfigKey, configAsVec);
+    service.addConfiguration(kConfigKey, configAsVec, String16(kAndroid.c_str()));
 }
 
 ConfigMetricsReport GetReports(StatsService& service) {
     vector<uint8_t> output;
-    service.getData(kConfigKey, &output);
+    service.getData(kConfigKey, String16(kAndroid.c_str()), &output);
     ConfigMetricsReportList reports;
     reports.ParseFromArray(output.data(), output.size());
     EXPECT_EQ(1, reports.reports_size());
@@ -134,4 +135,4 @@
 
 }  // namespace statsd
 }  // namespace os
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index fdc6c92..edfb8d0 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -136,6 +136,7 @@
 Landroid/app/ActivityThread$ServiceArgsData;->token:Landroid/os/IBinder;
 Landroid/app/ActivityThread;->sPackageManager:Landroid/content/pm/IPackageManager;
 Landroid/app/ActivityThread;->startActivityNow(Landroid/app/Activity;Ljava/lang/String;Landroid/content/Intent;Landroid/content/pm/ActivityInfo;Landroid/os/IBinder;Landroid/os/Bundle;Landroid/app/Activity$NonConfigurationInstances;)Landroid/app/Activity;
+Landroid/app/admin/DevicePolicyManager;->getMandatoryBackupTransport()Landroid/content/ComponentName;
 Landroid/app/admin/DevicePolicyManager;->getProfileOwnerAsUser(I)Landroid/content/ComponentName;
 Landroid/app/admin/DevicePolicyManager;->getTrustAgentConfiguration(Landroid/content/ComponentName;Landroid/content/ComponentName;I)Ljava/util/List;
 Landroid/app/admin/DevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
@@ -1500,7 +1501,6 @@
 Landroid/os/PowerManager;->getMinimumScreenBrightnessSetting()I
 Landroid/os/PowerManager;->isLightDeviceIdleMode()Z
 Landroid/os/PowerManager;->mService:Landroid/os/IPowerManager;
-Landroid/os/PowerManager;->nap(J)V
 Landroid/os/PowerManager;->userActivity(JZ)V
 Landroid/os/PowerManager;->validateWakeLockParameters(ILjava/lang/String;)V
 Landroid/os/PowerManager;->wakeUp(JLjava/lang/String;)V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index eba7471..a41da0e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5442,7 +5442,8 @@
      * runtime's instruction set is.
      */
     private String getInstrumentationLibrary(ApplicationInfo appInfo, InstrumentationInfo insInfo) {
-        if (appInfo.primaryCpuAbi != null && appInfo.secondaryCpuAbi != null) {
+        if (appInfo.primaryCpuAbi != null && appInfo.secondaryCpuAbi != null
+                && appInfo.secondaryCpuAbi.equals(insInfo.secondaryCpuAbi)) {
             // Get the instruction set supported by the secondary ABI. In the presence
             // of a native bridge this might be different than the one secondary ABI used.
             String secondaryIsa =
@@ -5671,6 +5672,16 @@
                         "Unable to find instrumentation info for: " + data.instrumentationName);
             }
 
+            // Warn of potential ABI mismatches.
+            if (!Objects.equals(data.appInfo.primaryCpuAbi, ii.primaryCpuAbi)
+                    || !Objects.equals(data.appInfo.secondaryCpuAbi, ii.secondaryCpuAbi)) {
+                Slog.w(TAG, "Package uses different ABI(s) than its instrumentation: "
+                        + "package[" + data.appInfo.packageName + "]: "
+                        + data.appInfo.primaryCpuAbi + ", " + data.appInfo.secondaryCpuAbi
+                        + " instrumentation[" + ii.packageName + "]: "
+                        + ii.primaryCpuAbi + ", " + ii.secondaryCpuAbi);
+            }
+
             mInstrumentationPackageName = ii.packageName;
             mInstrumentationAppDir = ii.sourceDir;
             mInstrumentationSplitAppDirs = ii.splitSourceDirs;
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 8783d94..45754ae 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -15,10 +15,13 @@
  */
 package android.app;
 
-import android.Manifest;
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.PACKAGE_USAGE_STATS;
+
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.os.IBinder;
 import android.os.IStatsManager;
 import android.os.RemoteException;
@@ -33,10 +36,13 @@
  */
 @SystemApi
 public final class StatsManager {
-    IStatsManager mService;
     private static final String TAG = "StatsManager";
     private static final boolean DEBUG = false;
 
+    private final Context mContext;
+
+    private IStatsManager mService;
+
     /**
      * Long extra of uid that added the relevant stats config.
      */
@@ -79,7 +85,8 @@
      *
      * @hide
      */
-    public StatsManager() {
+    public StatsManager(Context context) {
+        mContext = context;
     }
 
     /**
@@ -92,15 +99,18 @@
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      * @throws IllegalArgumentException if config is not a wire-encoded StatsdConfig proto
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public void addConfig(long configKey, byte[] config) throws StatsUnavailableException {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
-                service.addConfiguration(configKey, config); // can throw IllegalArgumentException
+                // can throw IllegalArgumentException
+                service.addConfiguration(configKey, config, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when adding configuration");
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -108,7 +118,7 @@
     /**
      * TODO: Temporary for backwards compatibility. Remove.
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean addConfiguration(long configKey, byte[] config) {
         try {
             addConfig(configKey, config);
@@ -124,15 +134,17 @@
      * @param configKey Configuration key to remove.
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public void removeConfig(long configKey) throws StatsUnavailableException {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
-                service.removeConfiguration(configKey);
+                service.removeConfiguration(configKey, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when removing configuration");
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -140,7 +152,7 @@
     /**
      * TODO: Temporary for backwards compatibility. Remove.
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean removeConfiguration(long configKey) {
         try {
             removeConfig(configKey);
@@ -179,7 +191,7 @@
      * @param subscriberId  ID of the subscriber, as used in the config.
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public void setBroadcastSubscriber(
             PendingIntent pendingIntent, long configKey, long subscriberId)
             throws StatsUnavailableException {
@@ -189,13 +201,17 @@
                 if (pendingIntent != null) {
                     // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
                     IBinder intentSender = pendingIntent.getTarget().asBinder();
-                    service.setBroadcastSubscriber(configKey, subscriberId, intentSender);
+                    service.setBroadcastSubscriber(configKey, subscriberId, intentSender,
+                            mContext.getOpPackageName());
                 } else {
-                    service.unsetBroadcastSubscriber(configKey, subscriberId);
+                    service.unsetBroadcastSubscriber(configKey, subscriberId,
+                            mContext.getOpPackageName());
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when adding broadcast subscriber", e);
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -203,7 +219,7 @@
     /**
      * TODO: Temporary for backwards compatibility. Remove.
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean setBroadcastSubscriber(
             long configKey, long subscriberId, PendingIntent pendingIntent) {
         try {
@@ -228,23 +244,26 @@
      * @param configKey     The integer naming the config to which this operation is attached.
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public void setFetchReportsOperation(PendingIntent pendingIntent, long configKey)
             throws StatsUnavailableException {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
                 if (pendingIntent == null) {
-                    service.removeDataFetchOperation(configKey);
+                    service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
                 } else {
                     // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
                     IBinder intentSender = pendingIntent.getTarget().asBinder();
-                    service.setDataFetchOperation(configKey, intentSender);
+                    service.setDataFetchOperation(configKey, intentSender,
+                            mContext.getOpPackageName());
                 }
 
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when registering data listener.");
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -252,7 +271,7 @@
     /**
      * TODO: Temporary for backwards compatibility. Remove.
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
         try {
             setFetchReportsOperation(pendingIntent, configKey);
@@ -270,15 +289,17 @@
      * @return Serialized ConfigMetricsReportList proto.
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public byte[] getReports(long configKey) throws StatsUnavailableException {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
-                return service.getData(configKey);
+                return service.getData(configKey, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when getting data");
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -286,7 +307,7 @@
     /**
      * TODO: Temporary for backwards compatibility. Remove.
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public @Nullable byte[] getData(long configKey) {
         try {
             return getReports(configKey);
@@ -303,15 +324,17 @@
      * @return Serialized StatsdStatsReport proto.
      * @throws StatsUnavailableException if unsuccessful due to failing to connect to stats service
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public byte[] getStatsMetadata() throws StatsUnavailableException {
         synchronized (this) {
             try {
                 IStatsManager service = getIStatsManagerLocked();
-                return service.getMetadata();
+                return service.getMetadata(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when getting metadata");
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (SecurityException e) {
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -323,7 +346,7 @@
      *
      * @return Serialized StatsdStatsReport proto. Returns null on failure (eg, if statsd crashed).
      */
-    @RequiresPermission(Manifest.permission.DUMP)
+    @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public @Nullable byte[] getMetadata() {
         try {
             return getStatsMetadata();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 246d4a3..db011da 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -458,11 +458,11 @@
             }});
 
         registerService(Context.STATS_MANAGER, StatsManager.class,
-                new StaticServiceFetcher<StatsManager>() {
-                    @Override
-                    public StatsManager createService() throws ServiceNotFoundException {
-                        return new StatsManager();
-                    }});
+                new CachedServiceFetcher<StatsManager>() {
+            @Override
+            public StatsManager createService(ContextImpl ctx) {
+                return new StatsManager(ctx.getOuterContext());
+            }});
 
         registerService(Context.STATUS_BAR_SERVICE, StatusBarManager.class,
                 new CachedServiceFetcher<StatusBarManager>() {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 61aaad2..2feb459 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4066,8 +4066,8 @@
      * immediately, without user approval. It is a best practice not to request this unless strictly
      * necessary since it opens up additional security vulnerabilities.
      *
-     * <p>Whether this key is offered to the user for approval at all or not depends on the
-     * {@code isUserSelectable} parameter.
+     * <p>Include {@link #INSTALLKEY_SET_USER_SELECTABLE} in the {@code flags} argument to allow
+     * the user to select the key from a dialog.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
      *        {@code null} if calling from a delegated certificate installer.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ee667c2..1b6b5a0 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -80,8 +80,7 @@
  * {@link #getBondedDevices()}; start device discovery with
  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
  * listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
- * Channels (CoC) connection requests with listenUsingL2capCoc(int)}; or start a scan for
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
  * </p>
  * <p>This class is thread safe.</p>
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 4ed2500..ef1b0bd 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -701,10 +701,14 @@
      * <p>If the local device has already exposed services when this function
      * is called, a service update notification will be sent to all clients.
      *
+     * <p>The {@link BluetoothGattServerCallback#onServiceAdded} callback will indicate
+     * whether this service has been added successfully. Do not add another service
+     * before this callback.
+     *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
      *
      * @param service Service to be added to the list of services provided by this device.
-     * @return true, if the service has been added successfully
+     * @return true, if the request to add service has been initiated
      */
     public boolean addService(BluetoothGattService service) {
         if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index c500116..dc17666 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -183,4 +183,6 @@
 
     void putCache(in String packageName, in Uri key, in Bundle value, int userId);
     Bundle getCache(in String packageName, in Uri key, int userId);
+
+    void resetTodayStats();
 }
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index abf9cc9..ded11cfd 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -21,23 +21,97 @@
 import android.util.Log;
 
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
 
 /** @hide */
 public class SyncStatusInfo implements Parcelable {
     private static final String TAG = "Sync";
 
-    static final int VERSION = 4;
+    static final int VERSION = 5;
 
     private static final int MAX_EVENT_COUNT = 10;
 
     public final int authorityId;
-    public long totalElapsedTime;
-    public int numSyncs;
-    public int numSourcePoll;
-    public int numSourceServer;
-    public int numSourceLocal;
-    public int numSourceUser;
-    public int numSourcePeriodic;
+
+    /**
+     * # of syncs for each sync source, etc.
+     */
+    public static class Stats {
+        public long totalElapsedTime;
+        public int numSyncs;
+        public int numSourcePoll;
+        public int numSourceOther;
+        public int numSourceLocal;
+        public int numSourceUser;
+        public int numSourcePeriodic;
+        public int numSourceFeed;
+        public int numFailures;
+        public int numCancels;
+
+        /** Copy all the stats to another instance. */
+        public void copyTo(Stats to) {
+            to.totalElapsedTime = totalElapsedTime;
+            to.numSyncs = numSyncs;
+            to.numSourcePoll = numSourcePoll;
+            to.numSourceOther = numSourceOther;
+            to.numSourceLocal = numSourceLocal;
+            to.numSourceUser = numSourceUser;
+            to.numSourcePeriodic = numSourcePeriodic;
+            to.numSourceFeed = numSourceFeed;
+            to.numFailures = numFailures;
+            to.numCancels = numCancels;
+        }
+
+        /** Clear all the stats. */
+        public void clear() {
+            totalElapsedTime = 0;
+            numSyncs = 0;
+            numSourcePoll = 0;
+            numSourceOther = 0;
+            numSourceLocal = 0;
+            numSourceUser = 0;
+            numSourcePeriodic = 0;
+            numSourceFeed = 0;
+            numFailures = 0;
+            numCancels = 0;
+        }
+
+        /** Write all the stats to a parcel. */
+        public void writeToParcel(Parcel parcel) {
+            parcel.writeLong(totalElapsedTime);
+            parcel.writeInt(numSyncs);
+            parcel.writeInt(numSourcePoll);
+            parcel.writeInt(numSourceOther);
+            parcel.writeInt(numSourceLocal);
+            parcel.writeInt(numSourceUser);
+            parcel.writeInt(numSourcePeriodic);
+            parcel.writeInt(numSourceFeed);
+            parcel.writeInt(numFailures);
+            parcel.writeInt(numCancels);
+        }
+
+        /** Read all the stats from a parcel. */
+        public void readFromParcel(Parcel parcel) {
+            totalElapsedTime = parcel.readLong();
+            numSyncs = parcel.readInt();
+            numSourcePoll = parcel.readInt();
+            numSourceOther = parcel.readInt();
+            numSourceLocal = parcel.readInt();
+            numSourceUser = parcel.readInt();
+            numSourcePeriodic = parcel.readInt();
+            numSourceFeed = parcel.readInt();
+            numFailures = parcel.readInt();
+            numCancels = parcel.readInt();
+        }
+    }
+
+    public long lastTodayResetTime;
+
+    public final Stats totalStats = new Stats();
+    public final Stats todayStats = new Stats();
+    public final Stats yesterdayStats = new Stats();
+
     public long lastSuccessTime;
     public int lastSuccessSource;
     public long lastFailureTime;
@@ -75,12 +149,15 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(VERSION);
         parcel.writeInt(authorityId);
-        parcel.writeLong(totalElapsedTime);
-        parcel.writeInt(numSyncs);
-        parcel.writeInt(numSourcePoll);
-        parcel.writeInt(numSourceServer);
-        parcel.writeInt(numSourceLocal);
-        parcel.writeInt(numSourceUser);
+
+        // Note we can't use Stats.writeToParcel() here; see the below constructor for the reason.
+        parcel.writeLong(totalStats.totalElapsedTime);
+        parcel.writeInt(totalStats.numSyncs);
+        parcel.writeInt(totalStats.numSourcePoll);
+        parcel.writeInt(totalStats.numSourceOther);
+        parcel.writeInt(totalStats.numSourceLocal);
+        parcel.writeInt(totalStats.numSourceUser);
+
         parcel.writeLong(lastSuccessTime);
         parcel.writeInt(lastSuccessSource);
         parcel.writeLong(lastFailureTime);
@@ -102,7 +179,18 @@
             parcel.writeLong(mLastEventTimes.get(i));
             parcel.writeString(mLastEvents.get(i));
         }
-        parcel.writeInt(numSourcePeriodic);
+        // Version 4
+        parcel.writeInt(totalStats.numSourcePeriodic);
+
+        // Version 5
+        parcel.writeInt(totalStats.numSourceFeed);
+        parcel.writeInt(totalStats.numFailures);
+        parcel.writeInt(totalStats.numCancels);
+
+        parcel.writeLong(lastTodayResetTime);
+
+        todayStats.writeToParcel(parcel);
+        yesterdayStats.writeToParcel(parcel);
     }
 
     public SyncStatusInfo(Parcel parcel) {
@@ -111,12 +199,15 @@
             Log.w("SyncStatusInfo", "Unknown version: " + version);
         }
         authorityId = parcel.readInt();
-        totalElapsedTime = parcel.readLong();
-        numSyncs = parcel.readInt();
-        numSourcePoll = parcel.readInt();
-        numSourceServer = parcel.readInt();
-        numSourceLocal = parcel.readInt();
-        numSourceUser = parcel.readInt();
+
+        // Note we can't use Stats.writeToParcel() here because the data is persisted and we need
+        // to be able to read from the old format too.
+        totalStats.totalElapsedTime = parcel.readLong();
+        totalStats.numSyncs = parcel.readInt();
+        totalStats.numSourcePoll = parcel.readInt();
+        totalStats.numSourceOther = parcel.readInt();
+        totalStats.numSourceLocal = parcel.readInt();
+        totalStats.numSourceUser = parcel.readInt();
         lastSuccessTime = parcel.readLong();
         lastSuccessSource = parcel.readInt();
         lastFailureTime = parcel.readLong();
@@ -149,25 +240,37 @@
         }
         if (version < 4) {
             // Before version 4, numSourcePeriodic wasn't persisted.
-            numSourcePeriodic = numSyncs - numSourceLocal - numSourcePoll - numSourceServer
-                    - numSourceUser;
-            if (numSourcePeriodic < 0) { // Sanity check.
-                numSourcePeriodic = 0;
+            totalStats.numSourcePeriodic =
+                    totalStats.numSyncs - totalStats.numSourceLocal - totalStats.numSourcePoll
+                            - totalStats.numSourceOther
+                            - totalStats.numSourceUser;
+            if (totalStats.numSourcePeriodic < 0) { // Sanity check.
+                totalStats.numSourcePeriodic = 0;
             }
         } else {
-            numSourcePeriodic = parcel.readInt();
+            totalStats.numSourcePeriodic = parcel.readInt();
+        }
+        if (version >= 5) {
+            totalStats.numSourceFeed = parcel.readInt();
+            totalStats.numFailures = parcel.readInt();
+            totalStats.numCancels = parcel.readInt();
+
+            lastTodayResetTime = parcel.readLong();
+
+            todayStats.readFromParcel(parcel);
+            yesterdayStats.readFromParcel(parcel);
         }
     }
 
     public SyncStatusInfo(SyncStatusInfo other) {
         authorityId = other.authorityId;
-        totalElapsedTime = other.totalElapsedTime;
-        numSyncs = other.numSyncs;
-        numSourcePoll = other.numSourcePoll;
-        numSourceServer = other.numSourceServer;
-        numSourceLocal = other.numSourceLocal;
-        numSourceUser = other.numSourceUser;
-        numSourcePeriodic = other.numSourcePeriodic;
+
+        other.totalStats.copyTo(totalStats);
+        other.todayStats.copyTo(todayStats);
+        other.yesterdayStats.copyTo(yesterdayStats);
+
+        lastTodayResetTime = other.lastTodayResetTime;
+
         lastSuccessTime = other.lastSuccessTime;
         lastSuccessSource = other.lastSuccessSource;
         lastFailureTime = other.lastFailureTime;
@@ -251,4 +354,41 @@
             }
         }
     }
+
+    /**
+     * If the last reset was not not today, move today's stats to yesterday's and clear today's.
+     */
+    public void maybeResetTodayStats(boolean clockValid, boolean force) {
+        final long now = System.currentTimeMillis();
+
+        if (!force) {
+            // Last reset was the same day, nothing to do.
+            if (areSameDates(now, lastTodayResetTime)) {
+                return;
+            }
+
+            // Hack -- on devices with no RTC, until the NTP kicks in, the device won't have the
+            // correct time. So if the time goes back, don't reset, unless we're sure the current
+            // time is correct.
+            if (now < lastTodayResetTime && !clockValid) {
+                return;
+            }
+        }
+
+        lastTodayResetTime = now;
+
+        todayStats.copyTo(yesterdayStats);
+        todayStats.clear();
+    }
+
+    private static boolean areSameDates(long time1, long time2) {
+        final Calendar c1 = new GregorianCalendar();
+        final Calendar c2 = new GregorianCalendar();
+
+        c1.setTimeInMillis(time1);
+        c2.setTimeInMillis(time2);
+
+        return c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)
+                && c1.get(Calendar.DAY_OF_YEAR) == c2.get(Calendar.DAY_OF_YEAR);
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/InstrumentationInfo.java b/core/java/android/content/pm/InstrumentationInfo.java
index 3faa951..fb2e4a04 100644
--- a/core/java/android/content/pm/InstrumentationInfo.java
+++ b/core/java/android/content/pm/InstrumentationInfo.java
@@ -101,6 +101,12 @@
     /** {@hide} */
     public String credentialProtectedDataDir;
 
+    /** {@hide} */
+    public String primaryCpuAbi;
+
+    /** {@hide} */
+    public String secondaryCpuAbi;
+
     /** {@hide} Full path to the directory containing primary ABI native libraries. */
     public String nativeLibraryDir;
 
@@ -131,6 +137,8 @@
         dataDir = orig.dataDir;
         deviceProtectedDataDir = orig.deviceProtectedDataDir;
         credentialProtectedDataDir = orig.credentialProtectedDataDir;
+        primaryCpuAbi = orig.primaryCpuAbi;
+        secondaryCpuAbi = orig.secondaryCpuAbi;
         nativeLibraryDir = orig.nativeLibraryDir;
         secondaryNativeLibraryDir = orig.secondaryNativeLibraryDir;
         handleProfiling = orig.handleProfiling;
@@ -160,6 +168,8 @@
         dest.writeString(dataDir);
         dest.writeString(deviceProtectedDataDir);
         dest.writeString(credentialProtectedDataDir);
+        dest.writeString(primaryCpuAbi);
+        dest.writeString(secondaryCpuAbi);
         dest.writeString(nativeLibraryDir);
         dest.writeString(secondaryNativeLibraryDir);
         dest.writeInt((handleProfiling == false) ? 0 : 1);
@@ -190,6 +200,8 @@
         dataDir = source.readString();
         deviceProtectedDataDir = source.readString();
         credentialProtectedDataDir = source.readString();
+        primaryCpuAbi = source.readString();
+        secondaryCpuAbi = source.readString();
         nativeLibraryDir = source.readString();
         secondaryNativeLibraryDir = source.readString();
         handleProfiling = source.readInt() != 0;
@@ -208,6 +220,8 @@
         ai.dataDir = dataDir;
         ai.deviceProtectedDataDir = deviceProtectedDataDir;
         ai.credentialProtectedDataDir = credentialProtectedDataDir;
+        ai.primaryCpuAbi = primaryCpuAbi;
+        ai.secondaryCpuAbi = secondaryCpuAbi;
         ai.nativeLibraryDir = nativeLibraryDir;
         ai.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
     }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1a5d3ac..262de15 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -864,7 +864,7 @@
 
     /**
      * <p>The camera device is a monochrome camera that doesn't contain a color filter array,
-     * and the pixel values on U and Y planes are all 128.</p>
+     * and the pixel values on U and V planes are all 128.</p>
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12;
diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl
index 3de953a..dd11d49 100644
--- a/core/java/android/os/IPermissionController.aidl
+++ b/core/java/android/os/IPermissionController.aidl
@@ -20,6 +20,7 @@
 /** @hide */
 interface IPermissionController {
     boolean checkPermission(String permission, int pid, int uid);
+    int noteOp(String op, int uid, String packageName);
     String[] getPackagesForUid(int uid);
     boolean isRuntimePermission(String permission);
     int getPackageUid(String packageName, int flags);
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 3b32c52..6b3b93a 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -80,14 +80,14 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    byte[] getData(in long key);
+    byte[] getData(in long key, in String packageName);
 
     /**
      * Fetches metadata across statsd. Returns byte array representing wire-encoded proto.
      *
      * Requires Manifest.permission.DUMP.
      */
-    byte[] getMetadata();
+    byte[] getMetadata(in String packageName);
 
     /**
      * Sets a configuration with the specified config key and subscribes to updates for this
@@ -97,7 +97,7 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void addConfiguration(in long configKey, in byte[] config);
+    void addConfiguration(in long configKey, in byte[] config, in String packageName);
 
     /**
      * Registers the given pending intent for this config key. This intent is invoked when the
@@ -106,14 +106,14 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void setDataFetchOperation(long configKey, in IBinder intentSender);
+    void setDataFetchOperation(long configKey, in IBinder intentSender, in String packageName);
 
     /**
      * Removes the data fetch operation for the specified configuration.
      *
      * Requires Manifest.permission.DUMP.
      */
-    void removeDataFetchOperation(long configKey);
+    void removeDataFetchOperation(long configKey, in String packageName);
 
     /**
      * Removes the configuration with the matching config key. No-op if this config key does not
@@ -121,7 +121,7 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void removeConfiguration(in long configKey);
+    void removeConfiguration(in long configKey, in String packageName);
 
     /**
      * Set the IIntentSender (i.e. PendingIntent) to be used when broadcasting subscriber
@@ -141,7 +141,8 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void setBroadcastSubscriber(long configKey, long subscriberId, in IBinder intentSender);
+    void setBroadcastSubscriber(long configKey, long subscriberId, in IBinder intentSender,
+                                in String packageName);
 
     /**
      * Undoes setBroadcastSubscriber() for the (configKey, subscriberId) pair.
@@ -150,5 +151,5 @@
      *
      * Requires Manifest.permission.DUMP.
      */
-    void unsetBroadcastSubscriber(long configKey, long subscriberId);
+    void unsetBroadcastSubscriber(long configKey, long subscriberId, in String packageName);
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index c00100b..9c25848 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
@@ -960,6 +961,7 @@
      *
      * @hide Requires signature permission.
      */
+    @TestApi
     public void nap(long time) {
         try {
             mService.nap(time);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 3f58afa..5b4b5f2 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -877,8 +877,12 @@
     SurfaceComposerClient::getHdrCapabilities(token, &capabilities);
 
     const auto& types = capabilities.getSupportedHdrTypes();
+    std::vector<int32_t> intTypes;
+    for (auto type : types) {
+        intTypes.push_back(static_cast<int32_t>(type));
+    }
     auto typesArray = env->NewIntArray(types.size());
-    env->SetIntArrayRegion(typesArray, 0, types.size(), types.data());
+    env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data());
 
     return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
             typesArray, capabilities.getDesiredMaxLuminance(),
diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto
index aa99ac7..db4a4c4 100644
--- a/core/proto/android/os/enums.proto
+++ b/core/proto/android/os/enums.proto
@@ -60,7 +60,7 @@
 // They are primarily used by android/os/HardwarePropertiesManager.java.
 // Any change to the types in the thermal hal should be made here as well.
 enum TemperatureTypeEnum {
-    TEMPERATURE_TYPE_UKNOWN = -1;
+    TEMPERATURE_TYPE_UNKNOWN = -1;
     TEMPERATURE_TYPE_CPU = 0;
     TEMPERATURE_TYPE_GPU = 1;
     TEMPERATURE_TYPE_BATTERY = 2;
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3571967..395b269 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4609,7 +4609,7 @@
     <string name="zen_mode_default_every_night_name">Sleeping</string>
 
     <!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] -->
-    <string name="muted_by">Muted by <xliff:g id="third_party">%1$s</xliff:g></string>
+    <string name="muted_by"><xliff:g id="third_party">%1$s</xliff:g> is muting some sounds</string>
 
     <!-- Error message shown when there is a system error which can be solved by user performing factory reset. [CHAR LIMIT=NONE] -->
     <string name="system_error_wipe_data">There\'s an internal problem with your device, and it may be unstable until you factory data reset.</string>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index ed29028..bde4943 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -175,6 +175,7 @@
     <assign-permission name="android.permission.DUMP" uid="statsd" />
     <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
     <assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
+    <assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="statsd" />
 
     <!-- This is a list of all the libraries available for application
          code to link against. -->
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index c1aa2dc..cfcecbc 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -576,18 +576,18 @@
         <item>0</item>  <item>334</item>
     </array>
     <array name="batterymeter_plus_points">
-        <item>3</item><item>0</item>
         <item>5</item><item>0</item>
-        <item>5</item><item>3</item>
-        <item>8</item><item>3</item>
-        <item>8</item><item>5</item>
-        <item>5</item><item>5</item>
-        <item>5</item><item>8</item>
-        <item>3</item><item>8</item>
-        <item>3</item><item>5</item>
+        <item>11</item><item>0</item>
+        <item>11</item><item>5</item>
+        <item>16</item><item>5</item>
+        <item>16</item><item>11</item>
+        <item>11</item><item>11</item>
+        <item>11</item><item>16</item>
+        <item>5</item><item>16</item>
+        <item>5</item><item>11</item>
+        <item>0</item><item>11</item>
         <item>0</item><item>5</item>
-        <item>0</item><item>3</item>
-        <item>3</item><item>3</item>
+        <item>5</item><item>5</item>
     </array>
 
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index e2f279a9..343191d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -393,16 +393,10 @@
                         mPlusFrame.top + mPlusPoints[1] * mPlusFrame.height());
             }
 
-            float fillPct = (mPlusFrame.bottom - levelTop) / (mPlusFrame.bottom - mPlusFrame.top);
-            fillPct = Math.min(Math.max(fillPct, 0), 1);
-            if (fillPct <= BOLT_LEVEL_THRESHOLD) {
-                // draw the plus if opaque
+            // Always cut out of the whole shape, and sometimes filled colorError
+            mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
+            if (mPowerSaveAsColorError) {
                 c.drawPath(mPlusPath, mPlusPaint);
-            } else {
-                mShapePath.op(mPlusPath, Path.Op.DIFFERENCE);
-                if (mPowerSaveAsColorError) {
-                    c.drawPath(mPlusPath, mPlusPaint);
-                }
             }
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index de29030..a53ff39 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -24,11 +24,10 @@
 import android.icu.util.MeasureUnit;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
-import com.android.internal.annotations.VisibleForTesting;
+
 import com.android.settingslib.R;
-import java.time.Clock;
+
 import java.time.Instant;
-import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
@@ -102,7 +101,7 @@
 
     private static String getMoreThanOneDayString(Context context, long drainTimeMs,
             String percentageString, boolean basedOnUsage) {
-        final long roundedTimeMs = roundToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
+        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
         CharSequence timeString = StringUtil.formatElapsedTime(context,
                 roundedTimeMs,
                 false /* withSeconds */);
@@ -139,7 +138,7 @@
             String percentageString, boolean basedOnUsage) {
         // Get the time of day we think device will die rounded to the nearest 15 min.
         final long roundedTimeOfDayMs =
-                roundToNearestThreshold(
+                roundTimeToNearestThreshold(
                         System.currentTimeMillis() + drainTimeMs,
                         FIFTEEN_MINUTES_MILLIS);
 
@@ -170,12 +169,24 @@
         return timeMs * 1000;
     }
 
-    private static long roundToNearestThreshold(long drainTime, long threshold) {
-        final long remainder = drainTime % threshold;
-        if (remainder < threshold / 2) {
-            return drainTime - remainder;
+    /**
+     * Rounds a time to the nearest multiple of the provided threshold. Note: This function takes
+     * the absolute value of the inputs since it is only meant to be used for times, not general
+     * purpose rounding.
+     *
+     * ex: roundTimeToNearestThreshold(41, 24) = 48
+     * @param drainTime The amount to round
+     * @param threshold The value to round to a multiple of
+     * @return The rounded value as a long
+     */
+    public static long roundTimeToNearestThreshold(long drainTime, long threshold) {
+        long time = Math.abs(drainTime);
+        long multiple = Math.abs(threshold);
+        final long remainder = time % multiple;
+        if (remainder < multiple / 2) {
+            return time - remainder;
         } else {
-            return drainTime - remainder + threshold;
+            return time - remainder + multiple;
         }
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index dfd48cc..f2ef99c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -175,4 +175,18 @@
         // Add percentage to string when provided
         assertThat(info2).isEqualTo("More than 2 days remaining (10%)");
     }
+
+    @Test
+    public void testRoundToNearestThreshold_roundsCorrectly() {
+        // test some pretty normal values
+        assertThat(PowerUtil.roundTimeToNearestThreshold(1200, 1000)).isEqualTo(1000);
+        assertThat(PowerUtil.roundTimeToNearestThreshold(800, 1000)).isEqualTo(1000);
+        assertThat(PowerUtil.roundTimeToNearestThreshold(1000, 1000)).isEqualTo(1000);
+
+        // test the weird stuff
+        assertThat(PowerUtil.roundTimeToNearestThreshold(80, -200)).isEqualTo(0);
+        assertThat(PowerUtil.roundTimeToNearestThreshold(-150, 100)).isEqualTo(200);
+        assertThat(PowerUtil.roundTimeToNearestThreshold(-120, 100)).isEqualTo(100);
+        assertThat(PowerUtil.roundTimeToNearestThreshold(-200, -75)).isEqualTo(225);
+    }
 }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 8b78366..28e8db9 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -83,7 +83,7 @@
     <string name="def_charging_started_sound" translatable="false">/system/media/audio/ui/ChargingStarted.ogg</string>
 
     <!-- sound trigger detection service default values -->
-    <integer name="def_max_sound_trigger_detection_service_ops_per_day" translatable="false">200</integer>
+    <integer name="def_max_sound_trigger_detection_service_ops_per_day" translatable="false">1000</integer>
     <integer name="def_sound_trigger_detection_service_op_timeout" translatable="false">15000</integer>
 
     <bool name="def_lockscreen_disabled">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 022e306..1d3e521 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2935,7 +2935,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 163;
+            private static final int SETTINGS_VERSION = 164;
 
             private final int mUserId;
 
@@ -3724,6 +3724,24 @@
                     currentVersion = 163;
                 }
 
+                if (currentVersion == 163) {
+                    // Version 163: Update default value of
+                    // MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY from old to new default
+                    final SettingsState settings = getGlobalSettingsLocked();
+                    final Setting currentSetting = settings.getSettingLocked(
+                            Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY);
+                    if (currentSetting.isDefaultFromSystem()) {
+                        settings.insertSettingLocked(
+                                Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
+                                Integer.toString(getContext().getResources().getInteger(
+                                        R.integer
+                                        .def_max_sound_trigger_detection_service_ops_per_day)),
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 164;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res/drawable/car_progress_bar.xml b/packages/SystemUI/res/drawable/car_progress_bar.xml
deleted file mode 100644
index 742fca7..0000000
--- a/packages/SystemUI/res/drawable/car_progress_bar.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-  Copyright (C) 2017 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License
--->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background">
-        <shape>
-            <solid android:color="@color/car_user_switcher_progress_bgcolor" />
-        </shape>
-    </item>
-
-    <item android:id="@android:id/progress">
-        <clip>
-            <shape>
-                <solid android:color="@color/car_user_switcher_progress_fgcolor" />
-            </shape>
-        </clip>
-    </item>
-</layer-list>
diff --git a/packages/SystemUI/res/drawable/car_round_button.xml b/packages/SystemUI/res/drawable/car_round_button.xml
deleted file mode 100644
index 5f4deb3..0000000
--- a/packages/SystemUI/res/drawable/car_round_button.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!--
-  Copyright (C) 2017 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <solid android:color="@color/car_start_driving_background" />
-    <corners android:radius="@dimen/car_start_driving_corner_radius" />
-</shape>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index c59b067..3242165 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -22,14 +22,13 @@
     android:alpha="0"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
-    android:gravity="fill_horizontal"
-    android:layout_marginTop="@dimen/car_padding_5"
-    android:layout_marginStart="@dimen/car_padding_4">
+    android:gravity="fill_horizontal">
 
     <ImageView android:id="@+id/user_avatar"
         android:layout_centerHorizontal="true"
         android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
         android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+        android:background="@drawable/car_button_ripple_background_inverse"
         />
 
     <TextView android:id="@+id/user_name"
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 27d0e46..d8b52fc 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -15,6 +15,7 @@
      limitations under the License.
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:fitsSystemWindows="true"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -31,34 +32,19 @@
             android:theme="@android:style/Theme"
             android:layout_alignParentTop="true"/>
 
-        <RelativeLayout
-            android:id="@+id/fullscreen_user_switcher_container"
-            android:layout_width="match_parent"
+        <!-- TODO: add app:verticallyCenterListContent="true" when car support lib is updated -->
+        <com.android.systemui.statusbar.car.UserGridRecyclerView
+            android:id="@+id/user_grid"
+            android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_marginStart="@dimen/car_margin"
-            android:layout_marginEnd="@dimen/car_margin">
-
-            <RelativeLayout
-                android:id="@+id/fullscreen_user_switcher_container_inner"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_marginEnd="@dimen/car_padding_4">
-
-                <com.android.systemui.statusbar.car.UserGridRecyclerView
-                    android:id="@+id/user_grid"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_below="@+id/header"
-                    android:scrollbars="vertical"
-                    android:scrollbarFadeDuration="0"
-                    android:verticalScrollbarPosition="left"
-                    android:layout_centerHorizontal="true"
-                    android:layout_centerVertical="true"
-                    android:layout_alignParentRight="true"/>
-
-            </RelativeLayout>
-
-        </RelativeLayout>
+            android:layout_below="@+id/header"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:layout_alignParentRight="true"
+            app:dayNightStyle="force_night"
+            app:showPagedListViewDivider="false"
+            app:gutter="both"
+            app:itemSpacing="@dimen/car_padding_5"/>
 
     </RelativeLayout>
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index c01bbce..9c2b95b 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -29,6 +29,7 @@
 
     <RelativeLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:id="@+id/user_switcher_container"
         android:layout_marginStart="@dimen/car_margin"
         android:layout_marginEnd="@dimen/car_margin"
@@ -36,23 +37,17 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/car_user_switcher_container_height">
 
-        <RelativeLayout
-            android:id="@+id/fullscreen_user_switcher_container_inner"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_marginEnd="@dimen/car_padding_4">
-
-            <com.android.systemui.statusbar.car.UserGridRecyclerView
-                android:id="@+id/user_grid"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:scrollbars="vertical"
-                android:verticalScrollbarPosition="left"
-                android:layout_centerHorizontal="true"
-                android:layout_centerVertical="true"
-                android:layout_alignParentRight="true"
-                android:scrollbarFadeDuration="0"/>
-        </RelativeLayout>
+        <com.android.systemui.statusbar.car.UserGridRecyclerView
+            android:id="@+id/user_grid"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:layout_alignParentRight="true"
+            app:dayNightStyle="force_night"
+            app:showPagedListViewDivider="false"
+            app:gutter="both"
+            app:itemSpacing="@dimen/car_padding_4"/>
 
     </RelativeLayout>
 
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index f424171..f554150 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -38,35 +38,49 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginStart="16dp"
         android:layout_gravity="center_vertical"
         android:gravity="end" >
 
-        <include
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical|start"
-            android:layout_marginEnd="8dp"
-            android:visibility="gone"
-            layout="@layout/mobile_signal_group" />
-
-        <com.android.keyguard.CarrierText
-            android:id="@+id/qs_carrier_text"
+        <LinearLayout
             android:layout_width="0dp"
-            android:layout_height="wrap_content"
+            android:layout_height="match_parent"
             android:layout_weight="1"
-            android:layout_gravity="center_vertical|start"
-            android:layout_marginEnd="32dp"
-            android:ellipsize="marquee"
-            android:textAppearance="@style/TextAppearance.QS.TileLabel"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textDirection="locale"
-            android:singleLine="true" />
+            android:gravity="center_vertical|start"
+            android:paddingStart="16dp">
+
+            <include
+                layout="@layout/mobile_signal_group"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone" />
+
+            <com.android.keyguard.CarrierText
+                android:id="@+id/qs_carrier_text"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_marginEnd="32dp"
+                android:ellipsize="marquee"
+                android:textAppearance="@style/TextAppearance.QS.TileLabel"
+                android:textColor="?android:attr/textColorPrimary"
+                android:textDirection="locale"
+                android:singleLine="true" />
+
+        </LinearLayout>
+
+        <com.android.systemui.qs.PageIndicator
+            android:id="@+id/footer_page_indicator"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical"
+            android:visibility="gone" />
 
         <com.android.keyguard.AlphaOptimizedLinearLayout
             android:id="@+id/qs_footer_actions_container"
-            android:layout_width="wrap_content"
+            android:layout_width="@integer/qs_footer_actions_width"
             android:layout_height="match_parent"
+            android:layout_weight="@integer/qs_footer_actions_weight"
             android:gravity="center_vertical|end" >
             <com.android.systemui.statusbar.phone.MultiUserSwitch
                 android:id="@+id/multi_user_switch"
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
index 00427cb..e96a09b 100644
--- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -19,9 +19,9 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingBottom="24dp"
     android:clipChildren="false"
-    android:clipToPadding="false">
+    android:clipToPadding="false"
+    android:paddingBottom="@dimen/qs_paged_tile_layout_padding_bottom">
 
     <FrameLayout
         android:id="@+id/page_decor"
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index c59492f..b81d363 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -35,4 +35,5 @@
     <integer name="quick_settings_num_columns">4</integer>
     <bool name="quick_settings_wide">true</bool>
     <dimen name="qs_detail_margin_top">0dp</dimen>
+    <dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-land/integers.xml b/packages/SystemUI/res/values-land/integers.xml
new file mode 100644
index 0000000..fb22665
--- /dev/null
+++ b/packages/SystemUI/res/values-land/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<resources>
+    <!-- Action footer width is set to 0 to allow it to stretch (through a weight of 1) and center
+         the page indicator in between the footer and the carrier text.-->
+    <integer name="qs_footer_actions_width">0</integer>
+    <integer name="qs_footer_actions_weight">1</integer>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1e55eb3..b220091 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -382,6 +382,7 @@
     <dimen name="qs_footer_padding_start">16dp</dimen>
     <dimen name="qs_footer_padding_end">16dp</dimen>
     <dimen name="qs_footer_icon_size">16dp</dimen>
+    <dimen name="qs_paged_tile_layout_padding_bottom">24dp</dimen>
 
     <dimen name="qs_notif_collapsed_space">64dp</dimen>
 
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 0cd3825..6bc8e26 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -16,9 +16,6 @@
 */
 -->
 <resources>
-    <dimen name="car_margin">148dp</dimen>
-    <dimen name="car_margin_standard">112dp</dimen>
-
     <!-- TODO replace with car support lib sizes when available -->
     <dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
     <dimen name="car_fullscreen_user_pod_width">243dp</dimen>
@@ -31,14 +28,6 @@
     <dimen name="car_left_navigation_bar_width">96dp</dimen>
     <dimen name="car_right_navigation_bar_width">96dp</dimen>
 
-    <dimen name="car_page_indicator_dot_diameter">12dp</dimen>
-    <dimen name="car_page_indicator_margin_bottom">24dp</dimen>
-
-    <dimen name="car_start_driving_corner_radius">16dp</dimen>
-    <dimen name="car_start_driving_padding_side">30dp</dimen>
-    <dimen name="car_start_driving_height">80dp</dimen>
-    <dimen name="car_start_driving_text_size">@dimen/car_body2_size</dimen>
-
     <dimen name="car_qs_footer_height">112dp</dimen>
     <dimen name="car_qs_footer_padding_bottom">16dp</dimen>
     <dimen name="car_qs_footer_padding_top">16dp</dimen>
diff --git a/packages/SystemUI/res/values/integers.xml b/packages/SystemUI/res/values/integers.xml
index 8f23283..87c4bbb 100644
--- a/packages/SystemUI/res/values/integers.xml
+++ b/packages/SystemUI/res/values/integers.xml
@@ -16,4 +16,9 @@
   -->
 <resources>
     <integer name="fingerprint_dialog_text_gravity">8388611</integer> <!-- gravity start -->
+
+    <!-- Action footer width used for layout_width to indicate WRAP_CONTENT (along with a weight of
+         0) as we can allow the carrier text to stretch as far as needed in the QS footer. -->
+    <integer name="qs_footer_actions_width">-2</integer>
+    <integer name="qs_footer_actions_weight">0</integer>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a4ea5e8..090d012 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -240,6 +240,8 @@
     <string name="accessibility_waiting_for_fingerprint">Waiting for fingerprint</string>
     <!-- Accessibility action of the unlock button when fingerpint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_unlock_without_fingerprint">Unlock without using your fingerprint</string>
+    <!-- Click action label for accessibility for the smart reply buttons (not shown on-screen).". [CHAR LIMIT=NONE] -->
+    <string name="accessibility_send_smart_reply">Send</string>
     <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
     <string name="unlock_label">unlock</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles_car.xml b/packages/SystemUI/res/values/styles_car.xml
deleted file mode 100644
index 2aaef86..0000000
--- a/packages/SystemUI/res/values/styles_car.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (c) 2017, The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <style name="CarUserSwitcher.StartDrivingButton" parent="@android:style/Widget.Material.Button">
-        <item name="android:background">@drawable/car_round_button</item>
-        <item name="android:textSize">@dimen/car_start_driving_text_size</item>
-        <item name="android:textColor">@color/car_start_driving_text</item>
-        <item name="android:paddingLeft">@dimen/car_start_driving_padding_side</item>
-        <item name="android:paddingRight">@dimen/car_start_driving_padding_side</item>
-    </style>
-</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index 2629f30..aa2f8d1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -45,7 +45,7 @@
     }
 
     public void setNumPages(int numPages) {
-        setVisibility(numPages > 1 ? View.VISIBLE : View.INVISIBLE);
+        setVisibility(numPages > 1 ? View.VISIBLE : View.GONE);
         if (mAnimating) {
             Log.w(TAG, "setNumPages during animation");
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index c548cf6..d8d07c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -46,6 +46,7 @@
     private final ArrayList<TilePage> mPages = new ArrayList<>();
 
     private PageIndicator mPageIndicator;
+    private float mPageIndicatorPosition;
 
     private int mNumPages;
     private PageListener mPageListener;
@@ -145,6 +146,8 @@
 
     public void setPageIndicator(PageIndicator indicator) {
         mPageIndicator = indicator;
+        mPageIndicator.setNumPages(mNumPages);
+        mPageIndicator.setLocation(mPageIndicatorPosition);
     }
 
     @Override
@@ -212,7 +215,6 @@
             }
             if (DEBUG) Log.d(TAG, "Size: " + mNumPages);
             mPageIndicator.setNumPages(mNumPages);
-            mPageIndicator.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE);
             setAdapter(mAdapter);
             mAdapter.notifyDataSetChanged();
             setCurrentItem(0, false);
@@ -221,6 +223,12 @@
 
     @Override
     public boolean updateResources() {
+        // Update bottom padding, useful for removing extra space once the panel page indicator is
+        // hidden.
+        setPadding(0, 0, 0,
+                getContext().getResources().getDimensionPixelSize(
+                        R.dimen.qs_paged_tile_layout_padding_bottom));
+
         boolean changed = false;
         for (int i = 0; i < mPages.size(); i++) {
             changed |= mPages.get(i).updateResources();
@@ -326,7 +334,8 @@
                 public void onPageScrolled(int position, float positionOffset,
                         int positionOffsetPixels) {
                     if (mPageIndicator == null) return;
-                    mPageIndicator.setLocation(position + positionOffset);
+                    mPageIndicatorPosition = position + positionOffset;
+                    mPageIndicator.setLocation(mPageIndicatorPosition);
                     if (mPageListener != null) {
                         mPageListener.onPageChanged(positionOffsetPixels == 0 &&
                                 (isLayoutRtl() ? position == mPages.size() - 1 : position == 0));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 28dd26f..abe819b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 
 import android.content.Context;
 import android.content.Intent;
@@ -35,6 +36,7 @@
 import android.view.View.OnClickListener;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
@@ -66,6 +68,7 @@
     private UserInfoController mUserInfoController;
     private SettingsButton mSettingsButton;
     protected View mSettingsContainer;
+    private PageIndicator mPageIndicator;
     private CarrierText mCarrierText;
 
     private boolean mQsDisabled;
@@ -108,6 +111,8 @@
                 Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
                         mQsPanel.showEdit(view)));
 
+        mPageIndicator = findViewById(R.id.footer_page_indicator);
+
         mSettingsButton = findViewById(R.id.settings_button);
         mSettingsContainer = findViewById(R.id.settings_button_container);
         mSettingsButton.setOnClickListener(this);
@@ -167,6 +172,14 @@
 
     private void updateResources() {
         updateFooterAnimator();
+
+        // Update the width and weight of the actions container as the page indicator can sometimes
+        // show and the layout needs to center it between the carrier text and actions container.
+        LinearLayout.LayoutParams params =
+                (LinearLayout.LayoutParams) mActionsContainer.getLayoutParams();
+        params.width = mContext.getResources().getInteger(R.integer.qs_footer_actions_width);
+        params.weight = mContext.getResources().getInteger(R.integer.qs_footer_actions_weight);
+        mActionsContainer.setLayoutParams(params);
     }
 
     private void updateFooterAnimator() {
@@ -181,6 +194,7 @@
                 .addFloat(mMobileGroup, "alpha", 0, 1)
                 .addFloat(mActionsContainer, "alpha", 0, 1)
                 .addFloat(mDragHandle, "alpha", 1, 0, 0)
+                .addFloat(mPageIndicator, "alpha", 0, 1)
                 .setStartDelay(0.15f)
                 .build();
     }
@@ -291,6 +305,7 @@
         mQsPanel = qsPanel;
         if (mQsPanel != null) {
             mMultiUserSwitch.setQsPanel(qsPanel);
+            mQsPanel.setFooterPageIndicator(mPageIndicator);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 3e1eed5..0876a5d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs;
 
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
 
 import android.annotation.Nullable;
@@ -63,7 +64,6 @@
     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
     protected final View mBrightnessView;
     private final H mHandler = new H();
-    private final View mPageIndicator;
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
     private final QSTileRevealController mQsTileRevealController;
 
@@ -75,6 +75,8 @@
     protected QSTileHost mHost;
 
     protected QSSecurityFooter mFooter;
+    private PageIndicator mPanelPageIndicator;
+    private PageIndicator mFooterPageIndicator;
     private boolean mGridContentVisible = true;
 
     protected QSTileLayout mTileLayout;
@@ -104,13 +106,13 @@
         mTileLayout.setListening(mListening);
         addView((View) mTileLayout);
 
-        mPageIndicator = LayoutInflater.from(context).inflate(
+        mPanelPageIndicator = (PageIndicator) LayoutInflater.from(context).inflate(
                 R.layout.qs_page_indicator, this, false);
-        addView(mPageIndicator);
+        addView(mPanelPageIndicator);
 
-        ((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator);
+        ((PagedTileLayout) mTileLayout).setPageIndicator(mPanelPageIndicator);
         mQsTileRevealController = new QSTileRevealController(mContext, this,
-                ((PagedTileLayout) mTileLayout));
+                (PagedTileLayout) mTileLayout);
 
         addDivider();
 
@@ -136,7 +138,7 @@
     }
 
     public View getPageIndicator() {
-        return mPageIndicator;
+        return mPanelPageIndicator;
     }
 
     public QSTileRevealController getQsTileRevealController() {
@@ -241,6 +243,38 @@
         }
     }
 
+    /**
+     * Links the footer's page indicator, which is used in landscape orientation to save space.
+     *
+     * @param pageIndicator indicator to use for page scrolling
+     */
+    public void setFooterPageIndicator(PageIndicator pageIndicator) {
+        if (mTileLayout instanceof PagedTileLayout) {
+            mFooterPageIndicator = pageIndicator;
+            updatePageIndicator();
+        }
+    }
+
+    private void updatePageIndicator() {
+        if (mTileLayout instanceof PagedTileLayout) {
+            // If we're in landscape, and we have the footer page indicator (which we should if the
+            // footer has been initialized & linked), then we'll show the footer page indicator to
+            // save space in the main QS tile area. Otherwise, we'll use the default one under the
+            // tiles/above the footer.
+            boolean shouldUseFooterPageIndicator =
+                    getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE
+                            && mFooterPageIndicator != null;
+
+            mPanelPageIndicator.setVisibility(View.GONE);
+            if (mFooterPageIndicator != null) {
+                mFooterPageIndicator.setVisibility(View.GONE);
+            }
+
+            ((PagedTileLayout) mTileLayout).setPageIndicator(
+                    shouldUseFooterPageIndicator ? mFooterPageIndicator : mPanelPageIndicator);
+        }
+    }
+
     public QSTileHost getHost() {
         return mHost;
     }
@@ -248,6 +282,9 @@
     public void updateResources() {
         final Resources res = mContext.getResources();
         setPadding(0, res.getDimensionPixelSize(R.dimen.qs_panel_padding_top), 0, res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom));
+
+        updatePageIndicator();
+
         for (TileRecord r : mRecords) {
             r.tile.clearState();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index d1913df..5d7dcbb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -375,9 +375,12 @@
         Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
                 insets.getDisplayCutout(), getDisplay());
         if (padding == null) {
-            setPadding(0, 0, 0, 0);
+            mSystemIconsView.setPaddingRelative(
+                    getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
+                    getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
         } else {
-            setPadding(padding.first, 0, padding.second, 0);
+            mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
+
         }
         return super.onApplyWindowInsets(insets);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index da21aa5..608a236 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -75,7 +75,7 @@
         mUserGridView = mUserSwitcherContainer.findViewById(R.id.user_grid);
         GridLayoutManager layoutManager = new GridLayoutManager(context,
                 context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
-        mUserGridView.setLayoutManager(layoutManager);
+        mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
         mUserGridView.buildAdapter();
 
         mUserSwitchCallback = new UserSwitchCallback();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index c1af1fa..6cb80c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -23,7 +23,6 @@
 import android.view.ViewStub;
 
 import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
 
 import com.android.settingslib.users.UserManagerHelper;
 import com.android.systemui.R;
@@ -49,7 +48,7 @@
         mUserGridView = mContainer.findViewById(R.id.user_grid);
         GridLayoutManager layoutManager = new GridLayoutManager(context,
                 context.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col));
-        mUserGridView.setLayoutManager(layoutManager);
+        mUserGridView.getRecyclerView().setLayoutManager(layoutManager);
         mUserGridView.buildAdapter();
         mUserGridView.setUserSelectionListener(this::onUserSelected);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5006a2c..41b70f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -16,19 +16,12 @@
 
 package com.android.systemui.statusbar.car;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.pm.UserInfo;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.GradientDrawable;
 import android.os.AsyncTask;
-import android.support.annotation.Nullable;
 import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -36,6 +29,8 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.car.widget.PagedListView;
+
 import com.android.settingslib.users.UserManagerHelper;
 import com.android.systemui.R;
 
@@ -46,7 +41,7 @@
  * Displays a GridLayout with icons for the users in the system to allow switching between users.
  * One of the uses of this is for the lock screen in auto.
  */
-public class UserGridRecyclerView extends RecyclerView implements
+public class UserGridRecyclerView extends PagedListView implements
         UserManagerHelper.OnUsersUpdateListener {
     private UserSelectionListener mUserSelectionListener;
     private UserAdapter mAdapter;
@@ -55,7 +50,6 @@
 
     public UserGridRecyclerView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        super.setHasFixedSize(true);
         mContext = context;
         mUserManagerHelper = new UserManagerHelper(mContext);
     }
@@ -65,6 +59,7 @@
      */
     @Override
     public void onFinishInflate() {
+        super.onFinishInflate();
         mUserManagerHelper.registerOnUsersUpdateListener(this);
     }
 
@@ -73,6 +68,7 @@
      */
     @Override
     public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
         mUserManagerHelper.unregisterOnUsersUpdateListener();
     }
 
@@ -152,8 +148,6 @@
 
         private final Context mContext;
         private List<UserRecord> mUsers;
-        private final int mPodImageAvatarWidth;
-        private final int mPodImageAvatarHeight;
         private final Resources mRes;
         private final String mGuestName;
         private final String mNewUserName;
@@ -162,10 +156,6 @@
             mRes = context.getResources();
             mContext = context;
             updateUsers(users);
-            mPodImageAvatarWidth = mRes.getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_image_avatar_width);
-            mPodImageAvatarHeight = mRes.getDimensionPixelSize(
-                    R.dimen.car_fullscreen_user_pod_image_avatar_height);
             mGuestName = mRes.getString(R.string.car_guest);
             mNewUserName = mRes.getString(R.string.car_new_user);
         }
@@ -190,13 +180,22 @@
         @Override
         public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
             UserRecord userRecord = mUsers.get(position);
-            holder.mUserAvatarImageView.setImageBitmap(getDefaultUserIcon(userRecord));
+            if (!userRecord.mIsAddUser) {
+                holder.mUserAvatarImageView.setImageBitmap(mUserManagerHelper
+                        .getUserIcon(userRecord.mInfo));
+            } else {
+                holder.mUserAvatarImageView.setImageDrawable(mContext
+                        .getDrawable(R.drawable.ic_add_circle_qs));
+            }
             holder.mUserNameTextView.setText(userRecord.mInfo.name);
             holder.mView.setOnClickListener(v -> {
                 if (userRecord == null) {
                     return;
                 }
 
+                // Disable button so it cannot be clicked multiple times
+                holder.mView.setEnabled(false);
+
                 // Notify the listener which user was selected
                 if (mUserSelectionListener != null) {
                     mUserSelectionListener.onUserSelected(userRecord);
@@ -244,57 +243,6 @@
             return mUsers.size();
         }
 
-        /**
-         * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
-         * the first character in the username.
-         *
-         * @param record the profile of the user for which the icon should be created
-         */
-        private Bitmap getDefaultUserIcon(UserRecord record) {
-            CharSequence displayText;
-            boolean isAddUserText = false;
-            if (record.mIsAddUser) {
-                displayText = "+";
-                isAddUserText = true;
-            } else {
-                displayText = record.mInfo.name.subSequence(0, 1);
-            }
-            Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(out);
-
-            // Draw the circle background.
-            GradientDrawable shape = new GradientDrawable();
-            shape.setShape(GradientDrawable.RADIAL_GRADIENT);
-            shape.setGradientRadius(1.0f);
-            shape.setColor(mContext.getColor(R.color.car_grey_50));
-            shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
-            shape.draw(canvas);
-
-            // Draw the letter in the center.
-            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            paint.setColor(mContext.getColor(R.color.car_grey_900));
-            paint.setTextAlign(Align.CENTER);
-            if (isAddUserText) {
-                paint.setTextSize(mRes.getDimensionPixelSize(
-                        R.dimen.car_touch_target_size));
-            } else {
-                paint.setTextSize(mRes.getDimensionPixelSize(
-                        R.dimen.car_fullscreen_user_pod_icon_text_size));
-            }
-
-            Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
-            // The Y coordinate is measured by taking half the height of the pod, but that would
-            // draw the character putting the bottom of the font in the middle of the pod.  To
-            // correct this, half the difference between the top and bottom distance metrics of the
-            // font gives the offset of the font.  Bottom is a positive value, top is negative, so
-            // the different is actually a sum.  The "half" operation is then factored out.
-            canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
-                    (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
-            return out;
-        }
-
         public class UserAdapterViewHolder extends RecyclerView.ViewHolder {
 
             public ImageView mUserAvatarImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 1fb1ddd..d9a55c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -232,8 +232,7 @@
         if (mCurrentlySecure) {
             alphaKeyguard = 1;
         } else {
-            alphaKeyguard = Math.max(0, Math.min(1, (y - mMinTopMargin)
-                    / Math.max(1f, getExpandedClockPosition() - mMinTopMargin)));
+            alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
             alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
         }
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 4e8003e..d6b45d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -449,6 +449,18 @@
         mScrimBehind.setDrawable(drawable);
     }
 
+    /**
+     * Sets the front alpha while in AOD.
+     */
+    public void setAodFrontScrimAlpha(float alpha) {
+        if (mState == ScrimState.AOD && mCurrentInFrontAlpha != alpha) {
+            mCurrentInFrontAlpha = alpha;
+            scheduleUpdate();
+        }
+
+        mState.AOD.setAodFrontScrimAlpha(alpha);
+    }
+
     protected void scheduleUpdate() {
         if (mUpdatePending) return;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index e7d5c4e..235b1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4883,7 +4883,7 @@
 
         @Override
         public void setAodDimmingScrim(float scrimOpacity) {
-            ScrimState.AOD.setAodFrontScrimAlpha(scrimOpacity);
+            mScrimController.setAodFrontScrimAlpha(scrimOpacity);
         }
 
         public void dispatchDoubleTap(float viewX, float viewY) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 4d86ae9..1431682 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -17,6 +17,8 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.widget.Button;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -179,6 +181,15 @@
             mKeyguardDismissUtil.dismissKeyguardThenExecute(
                     action, null /* cancelAction */, false /* afterKeyguardGone */);
         });
+
+        b.setAccessibilityDelegate(new AccessibilityDelegate() {
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                String label = getResources().getString(R.string.accessibility_send_smart_reply);
+                info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, label));
+            }
+        });
+
         return b;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index d78a6cb..c8fcfce 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -71,7 +71,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
+import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -1182,12 +1182,12 @@
                 }
             });
             mDialogView.setAccessibilityDelegate(this);
-            mAccessibilityMgr.addAccessibilityStateChangeListener(mListener);
+            mAccessibilityMgr.addCallback(mListener);
             updateFeedbackEnabled();
         }
 
         public void destroy() {
-            mAccessibilityMgr.removeAccessibilityStateChangeListener(mListener);
+            mAccessibilityMgr.removeCallback(mListener);
         }
 
         @Override
@@ -1213,7 +1213,7 @@
             return false;
         }
 
-        private final AccessibilityStateChangeListener mListener =
+        private final AccessibilityServicesStateChangeListener mListener =
                 enabled -> updateFeedbackEnabled();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 69508ac..4e04790 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -157,6 +157,38 @@
     }
 
     @Test
+    public void transitionToAod_withFrontAlphaUpdates() {
+        // Assert that setting the AOD front scrim alpha doesn't take effect in a non-AOD state.
+        mScrimController.transitionTo(ScrimState.KEYGUARD);
+        mScrimController.setAodFrontScrimAlpha(0.5f);
+        mScrimController.finishAnimationsImmediately();
+        // Front scrim should be transparent
+        // Back scrim should be visible without tint
+        assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT);
+
+        // ... but that it does take effect once we enter the AOD state.
+        mScrimController.transitionTo(ScrimState.AOD);
+        mScrimController.finishAnimationsImmediately();
+        // Front scrim should be semi-transparent
+        // Back scrim should be visible
+        assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_OPAQUE);
+
+        // ... and that if we set it while we're in AOD, it does take immediate effect.
+        mScrimController.setAodFrontScrimAlpha(1f);
+        assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
+
+        // ... and make sure we recall the previous front scrim alpha even if we transition away
+        // for a bit.
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.transitionTo(ScrimState.AOD);
+        mScrimController.finishAnimationsImmediately();
+        assertScrimVisibility(VISIBILITY_FULLY_OPAQUE, VISIBILITY_FULLY_OPAQUE);
+
+        // Reset value since enums are static.
+        mScrimController.setAodFrontScrimAlpha(0f);
+    }
+
+    @Test
     public void transitionToPulsing() {
         // Pre-condition
         // Need to go to AoD first because PULSING doesn't change
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 85eeba0..5c5f0f8 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -141,6 +141,13 @@
     static final int ALARM_EVENT = 1;
     static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
+    // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays
+    static final int ACTIVE_INDEX = 0;
+    static final int WORKING_INDEX = 1;
+    static final int FREQUENT_INDEX = 2;
+    static final int RARE_INDEX = 3;
+    static final int NEVER_INDEX = 4;
+
     private final Intent mBackgroundIntent
             = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND);
     static final IncreasingTimeOrder sIncreasingTimeOrder = new IncreasingTimeOrder();
@@ -381,9 +388,10 @@
                         DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
                 LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
                         DEFAULT_LISTENER_TIMEOUT);
-                APP_STANDBY_MIN_DELAYS[0] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[0],
-                        DEFAULT_APP_STANDBY_DELAYS[0]);
-                for (int i = 1; i < KEYS_APP_STANDBY_DELAY.length; i++) {
+                APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis(
+                        KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX],
+                        DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]);
+                for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) {
                     APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
                             Math.max(APP_STANDBY_MIN_DELAYS[i-1], DEFAULT_APP_STANDBY_DELAYS[i]));
                 }
@@ -1526,22 +1534,24 @@
         setImplLocked(a, false, doValidate);
     }
 
+    /**
+     * Return the minimum time that should elapse before an app in the specified bucket
+     * can receive alarms again
+     */
     private long getMinDelayForBucketLocked(int bucket) {
-        // Return the minimum time that should elapse before an app in the specified bucket
-        // can receive alarms again
-        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) {
-            return mConstants.APP_STANDBY_MIN_DELAYS[4];
-        }
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) {
-            return mConstants.APP_STANDBY_MIN_DELAYS[3];
-        }
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) {
-            return mConstants.APP_STANDBY_MIN_DELAYS[2];
-        }
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
-            return mConstants.APP_STANDBY_MIN_DELAYS[1];
-        }
-        else return mConstants.APP_STANDBY_MIN_DELAYS[0];
+        // UsageStats bucket values are treated as floors of their behavioral range.
+        // In other words, a bucket value between WORKING and ACTIVE is treated as
+        // WORKING, not as ACTIVE.  The ACTIVE and NEVER bucket apply only at specific
+        // values.
+        final int index;
+
+        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX;
+        else index = ACTIVE_INDEX;
+
+        return mConstants.APP_STANDBY_MIN_DELAYS[index];
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3a4de28..d2c0efb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8861,6 +8861,12 @@
         }
 
         @Override
+        public int noteOp(String op, int uid, String packageName) {
+            return mActivityManagerService.mAppOpsService
+                    .noteOperation(AppOpsManager.strOpToOp(op), uid, packageName);
+        }
+
+        @Override
         public String[] getPackagesForUid(int uid) {
             return mActivityManagerService.mContext.getPackageManager()
                     .getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index e34ee63..676f0c7 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -20,17 +20,16 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
+import android.graphics.BitmapFactory;
 import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
 import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.GradientDrawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.internal.R;
+import com.android.server.pm.UserManagerService;
+import java.io.FileDescriptor;
 
 /**
  * Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
@@ -60,54 +59,13 @@
         View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
             null);
 
+        FileDescriptor fileDescriptor = UserManagerService.getInstance()
+                .getUserIcon(mNewUser.id).getFileDescriptor();
+        Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
         ((ImageView) view.findViewById(R.id.user_loading_avatar))
-            .setImageBitmap(getDefaultUserIcon(mNewUser));
+            .setImageBitmap(bitmap);
         ((TextView) view.findViewById(R.id.user_loading))
             .setText(res.getString(R.string.car_loading_profile));
         setView(view);
     }
-
-    /**
-     * Returns the default user icon.  This icon is a circle with a letter in it.  The letter is
-     * the first character in the username.
-     *
-     * @param userInfo the profile of the user for which the icon should be created
-     */
-    private Bitmap getDefaultUserIcon(UserInfo userInfo) {
-        Resources res = mContext.getResources();
-        int mPodImageAvatarWidth = res.getDimensionPixelSize(
-            R.dimen.car_fullscreen_user_pod_image_avatar_width);
-        int mPodImageAvatarHeight = res.getDimensionPixelSize(
-            R.dimen.car_fullscreen_user_pod_image_avatar_height);
-        CharSequence displayText = userInfo.name.subSequence(0, 1);
-        Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
-            Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(out);
-
-        // Draw the circle background.
-        GradientDrawable shape = new GradientDrawable();
-        shape.setShape(GradientDrawable.RADIAL_GRADIENT);
-        shape.setGradientRadius(1.0f);
-        shape.setColor(mContext.getColor(R.color.car_user_switcher_user_image_bgcolor));
-        shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
-        shape.draw(canvas);
-
-        // Draw the letter in the center.
-        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        paint.setColor(mContext.getColor(R.color.car_user_switcher_user_image_fgcolor));
-        paint.setTextAlign(Align.CENTER);
-        paint.setTextSize(res.getDimensionPixelSize(
-            R.dimen.car_fullscreen_user_pod_icon_text_size));
-
-        Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
-        // The Y coordinate is measured by taking half the height of the pod, but that would
-        // draw the character putting the bottom of the font in the middle of the pod.  To
-        // correct this, half the difference between the top and bottom distance metrics of the
-        // font gives the offset of the font.  Bottom is a positive value, top is negative, so
-        // the different is actually a sum.  The "half" operation is then factored out.
-        canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
-            (mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
-
-        return out;
-    }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index ff1e29b..f2e44ee 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -80,8 +80,6 @@
             @NonNull RadioManager.BandConfig config);
     private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region);
 
-    private native void nativeSetMuted(long nativeContext, boolean mute);
-
     private native void nativeStep(long nativeContext, boolean directionDown, boolean skipSubChannel);
     private native void nativeScan(long nativeContext, boolean directionDown, boolean skipSubChannel);
     private native void nativeTune(long nativeContext, @NonNull ProgramSelector selector);
@@ -155,8 +153,7 @@
             checkNotClosedLocked();
             if (mIsMuted == mute) return;
             mIsMuted = mute;
-
-            nativeSetMuted(mNativeContext, mute);
+            Slog.w(TAG, "Mute via RadioService is not implemented - please handle it via app");
         }
     }
 
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 8f3f099..9833507 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -25,7 +25,6 @@
 import android.hardware.radio.ProgramList;
 import android.hardware.radio.ProgramSelector;
 import android.hardware.radio.RadioManager;
-import android.media.AudioSystem;
 import android.os.RemoteException;
 import android.util.MutableBoolean;
 import android.util.MutableInt;
@@ -45,7 +44,6 @@
     private final ITunerSession mHwSession;
     private final TunerCallback mCallback;
     private boolean mIsClosed = false;
-    private boolean mIsAudioConnected = false;
     private boolean mIsMuted = false;
 
     // necessary only for older APIs compatibility
@@ -56,7 +54,6 @@
         mModule = Objects.requireNonNull(module);
         mHwSession = Objects.requireNonNull(hwSession);
         mCallback = Objects.requireNonNull(callback);
-        notifyAudioServiceLocked(true);
     }
 
     @Override
@@ -64,7 +61,6 @@
         synchronized (mLock) {
             if (mIsClosed) return;
             mIsClosed = true;
-            notifyAudioServiceLocked(false);
         }
     }
 
@@ -79,22 +75,6 @@
         }
     }
 
-    private void notifyAudioServiceLocked(boolean connected) {
-        if (mIsAudioConnected == connected) return;
-
-        Slog.d(TAG, "Notifying AudioService about new state: " + connected);
-        int ret = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER,
-            connected ? AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE,
-            null, kAudioDeviceName);
-
-        if (ret == AudioSystem.AUDIO_STATUS_OK) {
-            mIsAudioConnected = connected;
-        } else {
-            Slog.e(TAG, "Failed to notify AudioService about new state: "
-                    + connected + ", response was: " + ret);
-        }
-    }
-
     @Override
     public void setConfiguration(RadioManager.BandConfig config) {
         synchronized (mLock) {
@@ -119,7 +99,7 @@
             checkNotClosedLocked();
             if (mIsMuted == mute) return;
             mIsMuted = mute;
-            notifyAudioServiceLocked(!mute);
+            Slog.w(TAG, "Mute via RadioService is not implemented - please handle it via app");
         }
     }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index e3d0bdd..e840a29 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -51,6 +51,8 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -1577,4 +1579,32 @@
             }
         }
     }
+
+    private void enforceShell(String method) {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
+            throw new SecurityException("Non-shell user attempted to call " + method);
+        }
+    }
+
+    @Override
+    public void resetTodayStats() {
+        enforceShell("resetTodayStats");
+
+        if (mSyncManager != null) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mSyncManager.resetTodayStats();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    }
+
+    @Override
+    public void onShellCommand(FileDescriptor in, FileDescriptor out,
+            FileDescriptor err, String[] args, ShellCallback callback,
+            ResultReceiver resultReceiver) {
+        (new ContentShellCommand(this)).exec(this, in, out, err, args, callback, resultReceiver);
+    }
 }
diff --git a/services/core/java/com/android/server/content/ContentShellCommand.java b/services/core/java/com/android/server/content/ContentShellCommand.java
new file mode 100644
index 0000000..6c2991f
--- /dev/null
+++ b/services/core/java/com/android/server/content/ContentShellCommand.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.content;
+
+import android.content.IContentService;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+public class ContentShellCommand extends ShellCommand {
+    final IContentService mInterface;
+
+    ContentShellCommand(IContentService service) {
+        mInterface = service;
+    }
+
+    @Override
+    public int onCommand(String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            switch(cmd) {
+                case "reset-today-stats":
+                    return runResetTodayStats();
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (RemoteException e) {
+            pw.println("Remote exception: " + e);
+        }
+        return -1;
+    }
+
+    private int runResetTodayStats() throws RemoteException {
+        mInterface.resetTodayStats();
+        return 0;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter pw = getOutPrintWriter();
+        pw.println("Content service commands:");
+        pw.println("  help");
+        pw.println("    Print this help text.");
+        pw.println("");
+        pw.println("  reset-today-stats");
+        pw.println("    Reset 1-day sync stats.");
+        pw.println();
+    }
+}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index a312fe1..decae18 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -48,6 +48,7 @@
 import android.content.SyncInfo;
 import android.content.SyncResult;
 import android.content.SyncStatusInfo;
+import android.content.SyncStatusInfo.Stats;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -95,6 +96,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.function.QuadConsumer;
 import com.android.server.DeviceIdleController;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -122,6 +124,7 @@
 import java.util.Objects;
 import java.util.Random;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 /**
@@ -242,7 +245,7 @@
     /** Track whether the device has already been provisioned. */
     private volatile boolean mProvisioned;
 
-    protected SyncAdaptersCache mSyncAdapters;
+    protected final SyncAdaptersCache mSyncAdapters;
 
     private final Random mRand;
 
@@ -423,6 +426,17 @@
                 }
             };
 
+    private final BroadcastReceiver mOtherIntentsReceiver =
+            new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+                        mSyncStorageEngine.setClockValid();
+                        return;
+                    }
+                }
+            };
+
     private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -631,6 +645,9 @@
         mContext.registerReceiverAsUser(
                 mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
 
+        intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
+        context.registerReceiver(mOtherIntentsReceiver, intentFilter);
+
         if (!factoryTest) {
             mNotificationMgr = (NotificationManager)
                     context.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -947,9 +964,13 @@
         } else if (requestedAuthority == null) {
             source = SyncStorageEngine.SOURCE_POLL;
         } else {
-            // This isn't strictly server, since arbitrary callers can (and do) request
-            // a non-forced two-way sync on a specific url.
-            source = SyncStorageEngine.SOURCE_SERVER;
+            if (extras.containsKey("feed")) {
+                source = SyncStorageEngine.SOURCE_FEED;
+            } else{
+                // This isn't strictly server, since arbitrary callers can (and do) request
+                // a non-forced two-way sync on a specific url.
+                source = SyncStorageEngine.SOURCE_OTHER;
+            }
         }
 
         for (AccountAndUser account : accounts) {
@@ -2134,6 +2155,7 @@
         pw.print("Memory low: "); pw.println(mStorageIsLow);
         pw.print("Device idle: "); pw.println(mDeviceIsIdle);
         pw.print("Reported active: "); pw.println(mReportedSyncActive);
+        pw.print("Clock valid: "); pw.println(mSyncStorageEngine.isClockValid());
 
         final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();
 
@@ -2181,26 +2203,35 @@
 
         final ArrayList<Pair<EndPoint, SyncStatusInfo>> statuses = new ArrayList<>();
 
+        mSyncStorageEngine.resetTodayStats(/* force=*/ false);
+
         for (AccountAndUser account : accounts) {
             pw.printf("Account %s u%d %s\n",
                     account.account.name, account.userId, account.account.type);
 
             pw.println("=======================================================================");
-            final PrintTable table = new PrintTable(13);
+            final PrintTable table = new PrintTable(16);
             table.set(0, 0,
                     "Authority", // 0
                     "Syncable",  // 1
                     "Enabled",   // 2
-                    "Delay",     // 3
-                    "Loc",       // 4
-                    "Poll",      // 5
-                    "Per",       // 6
-                    "Serv",      // 7
-                    "User",      // 8
-                    "Tot",       // 9
-                    "Time",      // 10
-                    "Last Sync", // 11
-                    "Backoff"    // 12
+
+                    "Stats",     // 3 "Total", "Today" or "Yesterday".
+
+                    "Loc",       // 4 # of syncs with local sources. (including failures/cancels. )
+                    "Poll",      // 5 "poll" syncs.
+                    "Per",       // 6 Periodic syncs.
+                    "Feed",      // 7 Syncs with a "feed" extra. (subscribedfeeds?)
+                    "User",      // 8 User-initiated
+                    "Othr",      // 9 Other sources.
+
+                    "Tot",       // 10 Total syncs (including failures / cancels)
+                    "Fail",      // 11 (Failure)
+                    "Can",       // 12 (Cancel)
+
+                    "Time",      // 13 Total time
+                    "Last Sync", // 14
+                    "Backoff"    // 15
             );
 
             final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -2234,37 +2265,50 @@
                 }
                 table.set(row, 0, authority, settings.syncable, settings.enabled);
 
-                sb.setLength(0);
-                table.set(row, 4,
-                        status.numSourceLocal,
-                        status.numSourcePoll,
-                        status.numSourcePeriodic,
-                        status.numSourceServer,
-                        status.numSourceUser,
-                        status.numSyncs,
-                        formatDurationHMS(sb, status.totalElapsedTime));
+                QuadConsumer<String, Stats, Function<Integer, String>, Integer> c =
+                        (label, stats, filter, r) -> {
+                    sb.setLength(0);
+                    table.set(r, 3,
+                            label,
+                            filter.apply(stats.numSourceLocal),
+                            filter.apply(stats.numSourcePoll),
+                            filter.apply(stats.numSourcePeriodic),
+                            filter.apply(stats.numSourceFeed),
+                            filter.apply(stats.numSourceUser),
+                            filter.apply(stats.numSourceOther),
+                            filter.apply(stats.numSyncs),
+                            filter.apply(stats.numFailures),
+                            filter.apply(stats.numCancels),
+                            formatDurationHMS(sb, stats.totalElapsedTime));
+                };
+                c.accept("Total", status.totalStats, (i) -> Integer.toString(i), row);
+                c.accept("Today", status.todayStats, this::zeroToEmpty, row + 1);
+                c.accept("Yestr", status.yesterdayStats, this::zeroToEmpty, row + 2);
+
+                final int LAST_SYNC = 14;
+                final int BACKOFF = LAST_SYNC + 1;
 
                 int row1 = row;
                 if (settings.delayUntil > now) {
-                    table.set(row1++, 12, "D: " + (settings.delayUntil - now) / 1000);
+                    table.set(row1++, BACKOFF, "D: " + (settings.delayUntil - now) / 1000);
                     if (settings.backoffTime > now) {
-                        table.set(row1++, 12, "B: " + (settings.backoffTime - now) / 1000);
-                        table.set(row1++, 12, settings.backoffDelay / 1000);
+                        table.set(row1++, BACKOFF, "B: " + (settings.backoffTime - now) / 1000);
+                        table.set(row1++, BACKOFF, settings.backoffDelay / 1000);
                     }
                 }
 
                 row1 = row;
                 if (status.lastSuccessTime != 0) {
-                    table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
+                    table.set(row1++, LAST_SYNC, SyncStorageEngine.SOURCES[status.lastSuccessSource]
                             + " " + "SUCCESS");
-                    table.set(row1++, 11, formatTime(status.lastSuccessTime));
+                    table.set(row1++, LAST_SYNC, formatTime(status.lastSuccessTime));
                 }
                 if (status.lastFailureTime != 0) {
-                    table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastFailureSource]
+                    table.set(row1++, LAST_SYNC, SyncStorageEngine.SOURCES[status.lastFailureSource]
                             + " " + "FAILURE");
-                    table.set(row1++, 11, formatTime(status.lastFailureTime));
+                    table.set(row1++, LAST_SYNC, formatTime(status.lastFailureTime));
                     //noinspection UnusedAssignment
-                    table.set(row1++, 11, status.lastFailureMesg);
+                    table.set(row1++, LAST_SYNC, status.lastFailureMesg);
                 }
             }
             table.writeTo(pw);
@@ -2274,6 +2318,7 @@
 
         pw.println();
         pw.println("Per Adapter History");
+        pw.println("(SERVER is now split up to FEED and OTHER)");
 
         for (int i = 0; i < statuses.size(); i++) {
             final Pair<EndPoint, SyncStatusInfo> event = statuses.get(i);
@@ -2299,6 +2344,10 @@
         }
     }
 
+    private String zeroToEmpty(int value) {
+        return (value != 0) ? Integer.toString(value) : "";
+    }
+
     private void dumpTimeSec(PrintWriter pw, long time) {
         pw.print(time/1000); pw.print('.'); pw.print((time/100)%10);
         pw.print('s');
@@ -2459,6 +2508,7 @@
 
             pw.println();
             pw.println("Recent Sync History");
+            pw.println("(SERVER is now split up to FEED and OTHER)");
             final String format = "  %-" + maxAccount + "s  %-" + maxAuthority + "s %s\n";
             final Map<String, Long> lastTimeMap = Maps.newHashMap();
             final PackageManager pm = mContext.getPackageManager();
@@ -2525,6 +2575,7 @@
             }
             pw.println();
             pw.println("Recent Sync History Extras");
+            pw.println("(SERVER is now split up to FEED and OTHER)");
             for (int i = 0; i < N; i++) {
                 final SyncStorageEngine.SyncHistoryItem item = items.get(i);
                 final Bundle extras = item.extras;
@@ -3104,6 +3155,10 @@
             final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
             if (isLoggable) Slog.v(TAG, op.toString());
 
+            // At this point, we know the device has been connected to the server, so
+            // assume the clock is correct.
+            mSyncStorageEngine.setClockValid();
+
             mSyncJobService.markSyncStarted(op.jobId);
 
             if (mStorageIsLow) {
@@ -4015,4 +4070,8 @@
         Slog.wtf(TAG, message);
         mLogger.log("WTF: ", message);
     }
+
+    public void resetTodayStats() {
+        mSyncStorageEngine.resetTodayStats(/*force=*/ true);
+    }
 }
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 8dd229c..f54a9a0 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -108,11 +108,12 @@
     /** Enum value for a sync stop event. */
     public static final int EVENT_STOP = 1;
 
-    /** Enum value for a server-initiated sync. */
-    public static final int SOURCE_SERVER = 0;
+    /** Enum value for a sync with other sources. */
+    public static final int SOURCE_OTHER = 0;
 
     /** Enum value for a local-initiated sync. */
     public static final int SOURCE_LOCAL = 1;
+
     /** Enum value for a poll-based sync (e.g., upon connection to network) */
     public static final int SOURCE_POLL = 2;
 
@@ -122,16 +123,18 @@
     /** Enum value for a periodic sync. */
     public static final int SOURCE_PERIODIC = 4;
 
+    /** Enum a sync with a "feed" extra */
+    public static final int SOURCE_FEED = 5;
+
     public static final long NOT_IN_BACKOFF_MODE = -1;
 
-    // TODO: i18n -- grab these out of resources.
     /** String names for the sync source types. */
-    public static final String[] SOURCES = { "SERVER",
+    public static final String[] SOURCES = { "OTHER",
             "LOCAL",
             "POLL",
             "USER",
             "PERIODIC",
-            "SERVICE"};
+            "FEED"};
 
     // The MESG column will contain one of these or one of the Error types.
     public static final String MESG_SUCCESS = "success";
@@ -153,6 +156,8 @@
     private static HashMap<String, String> sAuthorityRenames;
     private static PeriodicSyncAddedListener mPeriodicSyncAddedListener;
 
+    private volatile boolean mIsClockValid;
+
     static {
         sAuthorityRenames = new HashMap<String, String>();
         sAuthorityRenames.put("contacts", "com.android.contacts");
@@ -1174,23 +1179,36 @@
 
             SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
 
-            status.numSyncs++;
-            status.totalElapsedTime += elapsedTime;
+            status.maybeResetTodayStats(isClockValid(), /*force=*/ false);
+
+            status.totalStats.numSyncs++;
+            status.todayStats.numSyncs++;
+            status.totalStats.totalElapsedTime += elapsedTime;
+            status.todayStats.totalElapsedTime += elapsedTime;
             switch (item.source) {
                 case SOURCE_LOCAL:
-                    status.numSourceLocal++;
+                    status.totalStats.numSourceLocal++;
+                    status.todayStats.numSourceLocal++;
                     break;
                 case SOURCE_POLL:
-                    status.numSourcePoll++;
+                    status.totalStats.numSourcePoll++;
+                    status.todayStats.numSourcePoll++;
                     break;
                 case SOURCE_USER:
-                    status.numSourceUser++;
+                    status.totalStats.numSourceUser++;
+                    status.todayStats.numSourceUser++;
                     break;
-                case SOURCE_SERVER:
-                    status.numSourceServer++;
+                case SOURCE_OTHER:
+                    status.totalStats.numSourceOther++;
+                    status.todayStats.numSourceOther++;
                     break;
                 case SOURCE_PERIODIC:
-                    status.numSourcePeriodic++;
+                    status.totalStats.numSourcePeriodic++;
+                    status.todayStats.numSourcePeriodic++;
+                    break;
+                case SOURCE_FEED:
+                    status.totalStats.numSourceFeed++;
+                    status.todayStats.numSourceFeed++;
                     break;
             }
 
@@ -1225,6 +1243,9 @@
                 if (status.lastFailureTime == 0) {
                     writeStatusNow = true;
                 }
+                status.totalStats.numFailures++;
+                status.todayStats.numFailures++;
+
                 status.lastFailureTime = lastSyncTime;
                 status.lastFailureSource = item.source;
                 status.lastFailureMesg = resultMessage;
@@ -1233,6 +1254,11 @@
                 }
                 ds.failureCount++;
                 ds.failureTime += elapsedTime;
+            } else {
+                // Cancel
+                status.totalStats.numCancels++;
+                status.todayStats.numCancels++;
+                writeStatusNow = true;
             }
             final StringBuilder event = new StringBuilder();
             event.append("" + resultMessage + " Source=" + SyncStorageEngine.SOURCES[item.source]
@@ -1969,9 +1995,8 @@
     }
 
     /**
-     * Load sync engine state from the old syncmanager database, and then
-     * erase it.  Note that we don't deal with pending operations, active
-     * sync, or history.
+     * TODO Remove it. It's super old code that was used to migrate the information from a sqlite
+     * database that we used a long time ago, and is no longer relevant.
      */
     private void readAndDeleteLegacyAccountInfoLocked() {
         // Look for old database to initialize from.
@@ -2049,13 +2074,13 @@
                         st = new SyncStatusInfo(authority.ident);
                         mSyncStatus.put(authority.ident, st);
                     }
-                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
-                    st.numSyncs = getIntColumn(c, "numSyncs");
-                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
-                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
-                    st.numSourceServer = getIntColumn(c, "numSourceServer");
-                    st.numSourceUser = getIntColumn(c, "numSourceUser");
-                    st.numSourcePeriodic = 0;
+                    st.totalStats.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
+                    st.totalStats.numSyncs = getIntColumn(c, "numSyncs");
+                    st.totalStats.numSourceLocal = getIntColumn(c, "numSourceLocal");
+                    st.totalStats.numSourcePoll = getIntColumn(c, "numSourcePoll");
+                    st.totalStats.numSourceOther = getIntColumn(c, "numSourceServer");
+                    st.totalStats.numSourceUser = getIntColumn(c, "numSourceUser");
+                    st.totalStats.numSourcePeriodic = 0;
                     st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
                     st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
                     st.lastFailureSource = getIntColumn(c, "lastFailureSource");
@@ -2296,4 +2321,29 @@
     public void queueBackup() {
         BackupManager.dataChanged("android");
     }
+
+    public void setClockValid() {
+        if (!mIsClockValid) {
+            mIsClockValid = true;
+            Slog.w(TAG, "Clock is valid now.");
+        }
+    }
+
+    public boolean isClockValid() {
+        return mIsClockValid;
+    }
+
+    public void resetTodayStats(boolean force) {
+        if (force) {
+            Log.w(TAG, "Force resetting today stats.");
+        }
+        synchronized (mAuthorities) {
+            final int N = mSyncStatus.size();
+            for (int i = 0; i < N; i++) {
+                SyncStatusInfo cur = mSyncStatus.valueAt(i);
+                cur.maybeResetTodayStats(isClockValid(), force);
+            }
+            writeStatusLocked();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index cfec114..46e883c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -174,6 +174,12 @@
     // The default screen brightness.
     private final int mScreenBrightnessDefault;
 
+    // The minimum allowed brightness while in VR.
+    private final int mScreenBrightnessForVrRangeMinimum;
+
+    // The maximum allowed brightness while in VR.
+    private final int mScreenBrightnessForVrRangeMaximum;
+
     // The default screen brightness for VR.
     private final int mScreenBrightnessForVrDefault;
 
@@ -386,6 +392,11 @@
                     com.android.internal.R.integer.config_screenBrightnessSettingMaximum));
         mScreenBrightnessDefault = clampAbsoluteBrightness(resources.getInteger(
                     com.android.internal.R.integer.config_screenBrightnessSettingDefault));
+
+        mScreenBrightnessForVrRangeMinimum = clampAbsoluteBrightness(resources.getInteger(
+                    com.android.internal.R.integer.config_screenBrightnessForVrSettingMinimum));
+        mScreenBrightnessForVrRangeMaximum = clampAbsoluteBrightness(resources.getInteger(
+                    com.android.internal.R.integer.config_screenBrightnessForVrSettingMaximum));
         mScreenBrightnessForVrDefault = clampAbsoluteBrightness(resources.getInteger(
                     com.android.internal.R.integer.config_screenBrightnessForVrSettingDefault));
 
@@ -622,6 +633,9 @@
                 Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),
                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
         mContext.getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR),
+                false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
+        mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
                 false /*notifyForDescendants*/, mSettingsObserver, UserHandle.USER_ALL);
     }
@@ -1146,6 +1160,11 @@
         mReportedScreenStateToPolicy = state;
     }
 
+    private int clampScreenBrightnessForVr(int value) {
+        return MathUtils.constrain(
+                value, mScreenBrightnessForVrRangeMinimum, mScreenBrightnessForVrRangeMaximum);
+    }
+
     private int clampScreenBrightness(int value) {
         return MathUtils.constrain(
                 value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
@@ -1458,7 +1477,7 @@
         final int brightness = Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.SCREEN_BRIGHTNESS_FOR_VR, mScreenBrightnessForVrDefault,
                 UserHandle.USER_CURRENT);
-        return clampAbsoluteBrightness(brightness);
+        return clampScreenBrightnessForVr(brightness);
     }
 
     private void putScreenBrightnessSetting(int brightness) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 736aa46..0135085 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -248,6 +248,7 @@
     static final int WORKING_INDEX = 1;
     static final int FREQUENT_INDEX = 2;
     static final int RARE_INDEX = 3;
+    static final int NEVER_INDEX = 4;
 
     /**
      * Bookkeeping about when jobs last run.  We keep our own record in heartbeat time,
@@ -2432,11 +2433,11 @@
 
     public static int standbyBucketToBucketIndex(int bucket) {
         // Normalize AppStandby constants to indices into our bookkeeping
-        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) return 4;
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) return 3;
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) return 2;
-        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) return 1;
-        else return 0;
+        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) return NEVER_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) return RARE_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) return FREQUENT_INDEX;
+        else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) return WORKING_INDEX;
+        else return ACTIVE_INDEX;
     }
 
     // Static to support external callers
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index fb1874c..f1fd00b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -584,10 +584,43 @@
                 if (mUserManager.getUserInfo(userId).isManagedProfile()) {
                     tieManagedProfileLockIfNecessary(userId, null);
                 }
+
+                // If the user doesn't have a credential, try and derive their secret for the
+                // AuthSecret HAL. The secret will have been enrolled if the user previously set a
+                // credential and still needs to be passed to the HAL once that credential is
+                // removed.
+                if (mUserManager.getUserInfo(userId).isPrimary() && !isUserSecure(userId)) {
+                    tryDeriveAuthTokenForUnsecuredPrimaryUser(userId);
+                }
             }
         });
     }
 
+    private void tryDeriveAuthTokenForUnsecuredPrimaryUser(@UserIdInt int userId) {
+        synchronized (mSpManager) {
+            // Make sure the user has a synthetic password to derive
+            if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
+                return;
+            }
+
+            try {
+                final long handle = getSyntheticPasswordHandleLocked(userId);
+                final String noCredential = null;
+                AuthenticationResult result =
+                        mSpManager.unwrapPasswordBasedSyntheticPassword(
+                                getGateKeeperService(), handle, noCredential, userId, null);
+                if (result.authToken != null) {
+                    Slog.i(TAG, "Retrieved auth token for user " + userId);
+                    onAuthTokenKnownForUser(userId, result.authToken);
+                } else {
+                    Slog.e(TAG, "Auth token not available for user " + userId);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failure retrieving auth token", e);
+            }
+        }
+    }
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 6c0a7a7..5b8e8c0 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -71,6 +71,7 @@
 import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.os.Trace.TRACE_TAG_NETWORK;
 import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
 import static android.provider.Settings.Global.NETPOLICY_QUOTA_ENABLED;
 import static android.provider.Settings.Global.NETPOLICY_QUOTA_FRAC_JOBS;
@@ -1100,6 +1101,7 @@
      */
     void updateNotificationsNL() {
         if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
+        Trace.traceBegin(TRACE_TAG_NETWORK, "updateNotificationsNL");
 
         // keep track of previously active notifications
         final ArraySet<NotificationId> beforeNotifs = new ArraySet<NotificationId>(mActiveNotifs);
@@ -1191,6 +1193,8 @@
                 cancelNotification(notificationId);
             }
         }
+
+        Trace.traceEnd(TRACE_TAG_NETWORK);
     }
 
     /**
@@ -1604,6 +1608,7 @@
      */
     void updateNetworkEnabledNL() {
         if (LOGV) Slog.v(TAG, "updateNetworkEnabledNL()");
+        Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkEnabledNL");
 
         // TODO: reset any policy-disabled networks when any policy is removed
         // completely, which is currently rare case.
@@ -1633,6 +1638,7 @@
         }
 
         mStatLogger.logDurationStat(Stats.UPDATE_NETWORK_ENABLED, startTime);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
     }
 
     /**
@@ -1693,6 +1699,7 @@
      */
     void updateNetworkRulesNL() {
         if (LOGV) Slog.v(TAG, "updateNetworkRulesNL()");
+        Trace.traceBegin(TRACE_TAG_NETWORK, "updateNetworkRulesNL");
 
         final NetworkState[] states;
         try {
@@ -1866,6 +1873,8 @@
         mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
 
         mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
+
+        Trace.traceEnd(TRACE_TAG_NETWORK);
     }
 
     /**
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0563107..d2d3779 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -43,6 +43,7 @@
 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.os.Trace.TRACE_TAG_NETWORK;
 import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
 import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
 import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
@@ -109,6 +110,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -1189,27 +1191,43 @@
     private void recordSnapshotLocked(long currentTime) throws RemoteException {
         // snapshot and record current counters; read UID stats first to
         // avoid over counting dev stats.
+        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
         final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
+        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
         final NetworkStats xtSnapshot = getNetworkStatsXt();
+        Trace.traceEnd(TRACE_TAG_NETWORK);
+        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
         final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
+        Trace.traceEnd(TRACE_TAG_NETWORK);
 
         // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
         // providers that isn't already counted by dev and XT stats.
+        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether");
         final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
         xtSnapshot.combineAllValues(tetherSnapshot);
         devSnapshot.combineAllValues(tetherSnapshot);
 
         // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
         // can't be reattributed to responsible apps.
+        Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
         mDevRecorder.recordSnapshotLocked(
                 devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
+        Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
         mXtRecorder.recordSnapshotLocked(
                 xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
 
         // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
         VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
+        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
         mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
+        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
         mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
+        Trace.traceEnd(TRACE_TAG_NETWORK);
 
         // We need to make copies of member fields that are sent to the observer to avoid
         // a race condition between the service handler thread and the observer's
@@ -1254,8 +1272,7 @@
     private void performPollLocked(int flags) {
         if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
-
-        final long startRealtime = SystemClock.elapsedRealtime();
+        Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
 
         final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
         final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
@@ -1275,6 +1292,7 @@
         }
 
         // persist any pending data depending on requested flags
+        Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
         if (persistForce) {
             mDevRecorder.forcePersistLocked(currentTime);
             mXtRecorder.forcePersistLocked(currentTime);
@@ -1290,11 +1308,7 @@
                 mUidTagRecorder.maybePersistLocked(currentTime);
             }
         }
-
-        if (LOGV) {
-            final long duration = SystemClock.elapsedRealtime() - startRealtime;
-            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
-        }
+        Trace.traceEnd(TRACE_TAG_NETWORK);
 
         if (mSettings.getSampleEnabled()) {
             // sample stats after each full poll
@@ -1306,6 +1320,8 @@
         updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
                 READ_NETWORK_USAGE_HISTORY);
+
+        Trace.traceEnd(TRACE_TAG_NETWORK);
     }
 
     /**
@@ -1388,12 +1404,22 @@
     private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
         @Override
         public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
-            return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
+            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
+            try {
+                return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_NETWORK);
+            }
         }
 
         @Override
         public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
-            return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
+            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
+            try {
+                return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
+            } finally {
+                Trace.traceEnd(TRACE_TAG_NETWORK);
+            }
         }
 
         @Override
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index 864ce5d..3b3ee58 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -75,6 +75,7 @@
     private final WatchlistReportDbHelper mDbHelper;
     private final WatchlistConfig mConfig;
     private final WatchlistSettings mSettings;
+    private int mPrimaryUserId = -1;
     // A cache for uid and apk digest mapping.
     // As uid won't be reused until reboot, it's safe to assume uid is unique per signature and app.
     // TODO: Use more efficient data structure.
@@ -97,6 +98,7 @@
         mConfig = WatchlistConfig.getInstance();
         mSettings = WatchlistSettings.getInstance();
         mDropBoxManager = mContext.getSystemService(DropBoxManager.class);
+        mPrimaryUserId = getPrimaryUserId();
     }
 
     @Override
@@ -131,6 +133,19 @@
     }
 
     /**
+     * Get primary user id.
+     * @return Primary user id. -1 if primary user not found.
+     */
+    private int getPrimaryUserId() {
+        final UserInfo primaryUserInfo = ((UserManager) mContext.getSystemService(
+                Context.USER_SERVICE)).getPrimaryUser();
+        if (primaryUserInfo != null) {
+            return primaryUserInfo.id;
+        }
+        return -1;
+    }
+
+    /**
      * Return if a given package has testOnly is true.
      */
     private boolean isPackageTestOnly(int uid) {
@@ -182,6 +197,18 @@
         if (DEBUG) {
             Slog.i(TAG, "handleNetworkEvent with host: " + hostname + ", uid: " + uid);
         }
+        // Update primary user id if necessary
+        if (mPrimaryUserId == -1) {
+            mPrimaryUserId = getPrimaryUserId();
+        }
+
+        // Only process primary user data
+        if (UserHandle.getUserId(uid) != mPrimaryUserId) {
+            if (DEBUG) {
+                Slog.i(TAG, "Do not log non-system user records");
+            }
+            return;
+        }
         final String cncDomain = searchAllSubDomainsInWatchlist(hostname);
         if (cncDomain != null) {
             insertRecord(uid, cncDomain, timestamp);
@@ -272,28 +299,15 @@
     @VisibleForTesting
     List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
         // Step 1: Get all installed application digests.
-        final List<UserInfo> users = ((UserManager) mContext.getSystemService(
-                Context.USER_SERVICE)).getUsers();
-        final int totalUsers = users.size();
         final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
-                PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
+                PackageManager.MATCH_ALL);
         final HashSet<String> result = new HashSet<>(apps.size() + record.appDigestCNCList.size());
         final int size = apps.size();
         for (int i = 0; i < size; i++) {
-            final int appUid = apps.get(i).uid;
-            boolean added = false;
-            // As the uid returned by getInstalledApplications() is for primary user only, it
-            // may exist in secondary users but not primary user, so we need to loop and see if
-            // that user has the app enabled.
-            for (int j = 0; j < totalUsers && !added; j++) {
-                int uid = UserHandle.getUid(users.get(j).id, appUid);
-                byte[] digest = getDigestFromUid(uid);
-                if (digest != null) {
-                    result.add(HexDump.toHexString(digest));
-                    added = true;
-                }
-            }
-            if (!added) {
+            byte[] digest = getDigestFromUid(apps.get(i).uid);
+            if (digest != null) {
+                result.add(HexDump.toHexString(digest));
+            } else {
                 Slog.e(TAG, "Cannot get digest from uid: " + apps.get(i).uid
                         + ",pkg: " + apps.get(i).packageName);
             }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d5b2ee3..d112c02 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -782,18 +782,8 @@
         @Override
         public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
                 int uid, int initialPid, String message, int userId) {
-            Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
-                    + "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0, 0, false, userId,
                     REASON_ERROR, null);
-            long ident = Binder.clearCallingIdentity();
-            try {
-                ActivityManager.getService().crashApplication(uid, initialPid, pkg, -1,
-                        "Bad notification posted from package " + pkg
-                        + ": " + message);
-            } catch (RemoteException e) {
-            }
-            Binder.restoreCallingIdentity(ident);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index fb81ebf..fde13ac 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -312,12 +312,14 @@
                 return;
             }
 
-            // For backwards compatibility we accept match based on first signature only in the case
-            // of multiply-signed packagse
+            // For backwards compatibility we accept match based on any signature, since we may have
+            // recorded only the first for multiply-signed packages
             final String[] signaturesSha256Digests =
                     PackageUtils.computeSignaturesSha256Digests(pkg.mSigningDetails.signatures);
-            if (signaturesSha256Digests[0].equals(currentCookieSha256)) {
-                return;
+            for (String s : signaturesSha256Digests) {
+                if (s.equals(currentCookieSha256)) {
+                    return;
+                }
             }
 
             // Sorry, you are out of luck - different signatures - nuke data
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6ee4b5c..40c179f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11499,6 +11499,8 @@
                 a.info.dataDir = pkg.applicationInfo.dataDir;
                 a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir;
                 a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir;
+                a.info.primaryCpuAbi = pkg.applicationInfo.primaryCpuAbi;
+                a.info.secondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi;
                 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
                 a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir;
                 mInstrumentation.put(a.getComponentName(), a);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bba7772..61ce062 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1278,6 +1278,7 @@
 
         if (mContentInsetsChanged
                 || mVisibleInsetsChanged
+                || mStableInsetsChanged
                 || winAnimator.mSurfaceResized
                 || mOutsetsChanged
                 || mFrameSizeChanged
@@ -1701,12 +1702,17 @@
             return changed;
         }
 
-        if (visible != isVisibleNow()) {
-            if (!runningAppAnimation) {
+        final boolean isVisibleNow = isVisibleNow();
+        if (visible != isVisibleNow) {
+            // Run exit animation if:
+            // 1. App visibility and WS visibility are different
+            // 2. App is not running an animation
+            // 3. WS is currently visible
+            if (!runningAppAnimation && isVisibleNow) {
                 final AccessibilityController accessibilityController =
                         mService.mAccessibilityController;
-                final int winTransit = visible ? TRANSIT_ENTER : TRANSIT_EXIT;
-                mWinAnimator.applyAnimationLocked(winTransit, visible);
+                final int winTransit = TRANSIT_EXIT;
+                mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
                 //TODO (multidisplay): Magnification is supported only for the default
                 if (accessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
                     accessibilityController.onWindowTransitionLocked(this, winTransit);
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index a04697f..9c2e1e5 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -26,7 +26,6 @@
 #include <binder/IPCThreadState.h>
 #include <broadcastradio-utils-1x/Utils.h>
 #include <core_jni_helpers.h>
-#include <media/AudioSystem.h>
 #include <nativehelper/JNIHelp.h>
 #include <utils/Log.h>
 
@@ -70,8 +69,6 @@
     } Tuner;
 } gjni;
 
-static const char* const kAudioDeviceName = "Radio tuner source";
-
 class HalDeathRecipient : public hidl_death_recipient {
     wp<V1_1::ITunerCallback> mTunerCallback;
 
@@ -154,20 +151,6 @@
     return V1_1::IBroadcastRadio::castFrom(halModule).withDefault(nullptr);
 }
 
-// TODO(b/62713378): implement support for multiple tuners open at the same time
-static void notifyAudioService(TunerContext& ctx, bool connected) {
-    if (!ctx.mWithAudio) return;
-    if (ctx.mIsAudioConnected == connected) return;
-    ctx.mIsAudioConnected = connected;
-
-    ALOGD("Notifying AudioService about new state: %d", connected);
-    auto token = IPCThreadState::self()->clearCallingIdentity();
-    AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_IN_FM_TUNER,
-            connected ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-            nullptr, kAudioDeviceName);
-    IPCThreadState::self()->restoreCallingIdentity(token);
-}
-
 void assignHalInterfaces(JNIEnv *env, JavaRef<jobject> const &jTuner,
         sp<V1_0::IBroadcastRadio> halModule, sp<V1_0::ITuner> halTuner) {
     ALOGV("%s(%p)", __func__, halTuner.get());
@@ -193,8 +176,6 @@
 
     ctx.mHalDeathRecipient = new HalDeathRecipient(getNativeCallback(env, jTuner));
     halTuner->linkToDeath(ctx.mHalDeathRecipient, 0);
-
-    notifyAudioService(ctx, true);
 }
 
 static sp<V1_0::ITuner> getHalTuner(const TunerContext& ctx) {
@@ -236,8 +217,6 @@
 
     ALOGI("Closing tuner %p", ctx.mHalTuner.get());
 
-    notifyAudioService(ctx, false);
-
     ctx.mHalTuner->unlinkToDeath(ctx.mHalDeathRecipient);
     ctx.mHalDeathRecipient = nullptr;
 
@@ -280,14 +259,6 @@
     return convert::BandConfigFromHal(env, halConfig, region).release();
 }
 
-static void nativeSetMuted(JNIEnv *env, jobject obj, jlong nativeContext, bool mute) {
-    ALOGV("%s(%d)", __func__, mute);
-    lock_guard<mutex> lk(gContextMutex);
-    auto& ctx = getNativeContext(nativeContext);
-
-    notifyAudioService(ctx, !mute);
-}
-
 static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext,
         bool directionDown, bool skipSubChannel) {
     ALOGV("%s", __func__);
@@ -467,7 +438,6 @@
             (void*)nativeSetConfiguration },
     { "nativeGetConfiguration", "(JI)Landroid/hardware/radio/RadioManager$BandConfig;",
             (void*)nativeGetConfiguration },
-    { "nativeSetMuted", "(JZ)V", (void*)nativeSetMuted },
     { "nativeStep", "(JZZ)V", (void*)nativeStep },
     { "nativeScan", "(JZZ)V", (void*)nativeScan },
     { "nativeTune", "(JLandroid/hardware/radio/ProgramSelector;)V", (void*)nativeTune },
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5519d22..74b40ba 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1111,45 +1111,47 @@
             }
             traceEnd();
 
-            if (context.getPackageManager().hasSystemFeature(
-                        PackageManager.FEATURE_WIFI)) {
-                // Wifi Service must be started first for wifi-related services.
-                traceBeginAndSlog("StartWifi");
-                mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
-                traceEnd();
-                traceBeginAndSlog("StartWifiScanning");
-                mSystemServiceManager.startService(
-                    "com.android.server.wifi.scanner.WifiScanningService");
-                traceEnd();
-            }
+            if (!mOnlyCore) {
+                if (context.getPackageManager().hasSystemFeature(
+                            PackageManager.FEATURE_WIFI)) {
+                    // Wifi Service must be started first for wifi-related services.
+                    traceBeginAndSlog("StartWifi");
+                    mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
+                    traceEnd();
+                    traceBeginAndSlog("StartWifiScanning");
+                    mSystemServiceManager.startService(
+                        "com.android.server.wifi.scanner.WifiScanningService");
+                    traceEnd();
+                }
 
-            if (context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_WIFI_RTT)) {
-                traceBeginAndSlog("StartRttService");
-                mSystemServiceManager.startService(
-                    "com.android.server.wifi.rtt.RttService");
-                traceEnd();
-            }
+                if (context.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_WIFI_RTT)) {
+                    traceBeginAndSlog("StartRttService");
+                    mSystemServiceManager.startService(
+                        "com.android.server.wifi.rtt.RttService");
+                    traceEnd();
+                }
 
-            if (context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_WIFI_AWARE)) {
-                traceBeginAndSlog("StartWifiAware");
-                mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
-                traceEnd();
-            }
+                if (context.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_WIFI_AWARE)) {
+                    traceBeginAndSlog("StartWifiAware");
+                    mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
+                    traceEnd();
+                }
 
-            if (context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_WIFI_DIRECT)) {
-                traceBeginAndSlog("StartWifiP2P");
-                mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
-                traceEnd();
-            }
+                if (context.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_WIFI_DIRECT)) {
+                    traceBeginAndSlog("StartWifiP2P");
+                    mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
+                    traceEnd();
+                }
 
-            if (context.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_LOWPAN)) {
-                traceBeginAndSlog("StartLowpan");
-                mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
-                traceEnd();
+                if (context.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_LOWPAN)) {
+                    traceBeginAndSlog("StartLowpan");
+                    mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
+                    traceEnd();
+                }
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 96f8160..2dc3510 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -25,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.IActivityManager;
+import android.app.KeyguardManager;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManagerInternal;
@@ -102,7 +103,8 @@
         LocalServices.addService(DevicePolicyManagerInternal.class, mDevicePolicyManagerInternal);
 
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
-                mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class));
+                mDevicePolicyManager, mock(StorageManager.class), mock(TrustManager.class),
+                mock(KeyguardManager.class));
         mStorage = new LockSettingsStorageTestable(mContext,
                 new File(getContext().getFilesDir(), "locksettings"));
         File storageDir = mStorage.mStorageDir;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 237091d..6e1f357 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.app.KeyguardManager;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
@@ -79,7 +80,7 @@
 
         MockLockSettingsContext context = new MockLockSettingsContext(getContext(), mockUserManager,
                 mock(NotificationManager.class), mock(DevicePolicyManager.class),
-                mock(StorageManager.class), mock(TrustManager.class));
+                mock(StorageManager.class), mock(TrustManager.class), mock(KeyguardManager.class));
         mStorage = new LockSettingsStorageTestable(context,
                 new File(getContext().getFilesDir(), "locksettings"));
         mStorage.setDatabaseOnCreateCallback(new LockSettingsStorage.Callback() {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
index 3ad30f3..b332532 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/MockLockSettingsContext.java
@@ -16,6 +16,7 @@
 
 package com.android.server.locksettings;
 
+import android.app.KeyguardManager;
 import android.app.NotificationManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
@@ -32,16 +33,19 @@
     private DevicePolicyManager mDevicePolicyManager;
     private StorageManager mStorageManager;
     private TrustManager mTrustManager;
+    private KeyguardManager mKeyguardManager;
 
     public MockLockSettingsContext(Context base, UserManager userManager,
             NotificationManager notificationManager, DevicePolicyManager devicePolicyManager,
-            StorageManager storageManager, TrustManager trustManager) {
+            StorageManager storageManager, TrustManager trustManager,
+            KeyguardManager keyguardManager) {
         super(base);
         mUserManager = userManager;
         mNotificationManager = notificationManager;
         mDevicePolicyManager = devicePolicyManager;
         mStorageManager = storageManager;
         mTrustManager = trustManager;
+        mKeyguardManager = keyguardManager;
     }
 
     @Override
@@ -56,6 +60,8 @@
             return mStorageManager;
         } else if (TRUST_SERVICE.equals(name)) {
             return mTrustManager;
+        } else if (KEYGUARD_SERVICE.equals(name)) {
+            return mKeyguardManager;
         } else {
             throw new RuntimeException("System service not mocked: " + name);
         }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index e9f9800..142b950 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -217,6 +217,38 @@
         verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
     }
 
+    public void testNoSyntheticPasswordOrCredentialDoesNotPassAuthSecret() throws RemoteException {
+        // Setting null doesn't create a synthetic password
+        initializeCredentialUnderSP(null, PRIMARY_USER_ID);
+
+        reset(mAuthSecretService);
+        mService.onUnlockUser(PRIMARY_USER_ID);
+        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
+    }
+
+    public void testSyntheticPasswordAndCredentialDoesNotPassAuthSecret() throws RemoteException {
+        final String PASSWORD = "passwordForASyntheticPassword";
+        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+
+        reset(mAuthSecretService);
+        mService.onUnlockUser(PRIMARY_USER_ID);
+        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
+    }
+
+    public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
+        final String PASSWORD = "getASyntheticPassword";
+        initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, PASSWORD,
+                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+
+        reset(mAuthSecretService);
+        mService.onUnlockUser(PRIMARY_USER_ID);
+        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
+    }
+
     public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
         final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd";
         disableSyntheticPassword();
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
index a38b353..8399dac 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
@@ -63,8 +63,10 @@
 
     private static final String APK_A = "A.apk";
     private static final String APK_B = "B.apk";
+    private static final String APK_C = "C.apk";
     private static final String APK_A_CONTENT = "AAA";
     private static final String APK_B_CONTENT = "BBB";
+    private static final String APK_C_CONTENT = "CCC";
     // Sha256 of "AAA"
     private static final String APK_A_CONTENT_HASH =
             "CB1AD2119D8FAFB69566510EE712661F9F14B83385006EF92AEC47F523A38358";
@@ -120,8 +122,9 @@
             return result;
         }).when(mockPackageManager).getInstalledApplications(anyInt());
 
-        // Uid 1 app with is installed in primary user and package name is "A"
-        // Uid 2 app is installed in secondary user and package name is "B"
+        // Uid 1 app is installed in primary user only and package name is "A"
+        // Uid 2 app is installed in both primary user and secondary user, package name is "B"
+        // Uid 3 app is installed in secondary user and package name is "C"
         doAnswer((InvocationOnMock invocation) -> {
             int uid = (int) invocation.getArguments()[0];
             if (uid == 1) {
@@ -129,9 +132,13 @@
             } else if (uid == 1000001) {
                 return null;
             } else if (uid == 2) {
-                return null;
+                return new String[]{"B"};
             } else if (uid == 1000002) {
                 return new String[]{"B"};
+            } else if (uid == 3) {
+                return null;
+            } else if (uid == 1000002) {
+                return new String[]{"C"};
             }
             return null;
         }).when(mockPackageManager).getPackagesForUid(anyInt());
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 125161d..a39992b 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -148,7 +148,7 @@
         UiccSlotInfo that = (UiccSlotInfo) obj;
         return (mIsActive == that.mIsActive)
                 && (mIsEuicc == that.mIsEuicc)
-                && (mCardId == that.mCardId)
+                && (Objects.equals(mCardId, that.mCardId))
                 && (mCardStateInfo == that.mCardStateInfo)
                 && (mLogicalSlotIdx == that.mLogicalSlotIdx)
                 && (mIsExtendedApduSupported == that.mIsExtendedApduSupported);
diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
index 0504c79..dcbbdbb 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.os.BinderInternal;
 
+import android.app.AppOpsManager;
 import android.os.Binder;
 import android.os.IPermissionController;
 import android.os.RemoteException;
@@ -49,11 +50,17 @@
     public void testSetPermissionController() {
         try {
             IPermissionController pc = new IPermissionController.Stub() {
+                @Override
                 public boolean checkPermission(java.lang.String permission, int pid, int uid) {
                     return true;
                 }
 
                 @Override
+                public int noteOp(String op, int uid, String packageName) {
+                    return AppOpsManager.MODE_ALLOWED;
+                }
+
+                @Override
                 public String[] getPackagesForUid(int uid) {
                     return new String[0];
                 }