Merge "Per-test WindowManagerService instance"
diff --git a/api/current.txt b/api/current.txt
index ec16f1e..969d7bd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23371,6 +23371,18 @@
     method public void onAudioFocusChange(int);
   }
 
+  public final class AudioPlaybackCaptureConfiguration {
+  }
+
+  public static final class AudioPlaybackCaptureConfiguration.Builder {
+    ctor public AudioPlaybackCaptureConfiguration.Builder();
+    method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
+    method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
+    method public android.media.AudioPlaybackCaptureConfiguration build();
+    method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
+    method public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(@NonNull android.media.AudioAttributes);
+  }
+
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.AudioAttributes getAudioAttributes();
@@ -23469,6 +23481,7 @@
     ctor public AudioRecord.Builder();
     method public android.media.AudioRecord build() throws java.lang.UnsupportedOperationException;
     method public android.media.AudioRecord.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioRecord.Builder setAudioPlaybackCaptureConfig(@NonNull android.media.AudioPlaybackCaptureConfiguration);
     method public android.media.AudioRecord.Builder setAudioSource(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioRecord.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
   }
@@ -44259,6 +44272,7 @@
     field public static final String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
     field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
     field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
+    field public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY = "emergency_number_prefix_string_array";
     field public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
     field public static final String KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL = "enhanced_4g_lte_on_by_default_bool";
     field public static final String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 653ef2e..a6699e7 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -298,7 +298,7 @@
 void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigKey& key,
                                         const StatsdConfig& config) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-    WriteDataToDiskLocked(key, timestampNs, CONFIG_UPDATED);
+    WriteDataToDiskLocked(key, timestampNs, CONFIG_UPDATED, NO_TIME_CONSTRAINTS);
     OnConfigUpdatedLocked(timestampNs, key, config);
 }
 
@@ -355,6 +355,7 @@
                                      const bool include_current_partial_bucket,
                                      const bool erase_data,
                                      const DumpReportReason dumpReportReason,
+                                     const DumpLatency dumpLatency,
                                      ProtoOutputStream* proto) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
 
@@ -378,8 +379,10 @@
         // Start of ConfigMetricsReport (reports).
         uint64_t reportsToken =
                 proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
-        onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket,
-                                    erase_data, dumpReportReason, proto);
+        onConfigMetricsReportLocked(key, dumpTimeStampNs,
+                                    include_current_partial_bucket,
+                                    erase_data, dumpReportReason,
+                                    dumpLatency, proto);
         proto->end(reportsToken);
         // End of ConfigMetricsReport (reports).
     } else {
@@ -394,10 +397,11 @@
                                      const bool include_current_partial_bucket,
                                      const bool erase_data,
                                      const DumpReportReason dumpReportReason,
+                                     const DumpLatency dumpLatency,
                                      vector<uint8_t>* outData) {
     ProtoOutputStream proto;
     onDumpReport(key, dumpTimeStampNs, include_current_partial_bucket, erase_data,
-                 dumpReportReason, &proto);
+                 dumpReportReason, dumpLatency, &proto);
 
     if (outData != nullptr) {
         outData->clear();
@@ -423,6 +427,7 @@
                                                     const bool include_current_partial_bucket,
                                                     const bool erase_data,
                                                     const DumpReportReason dumpReportReason,
+                                                    const DumpLatency dumpLatency,
                                                     ProtoOutputStream* proto) {
     // We already checked whether key exists in mMetricsManagers in
     // WriteDataToDisk.
@@ -438,7 +443,7 @@
     // First, fill in ConfigMetricsReport using current data on memory, which
     // starts from filling in StatsLogReport's.
     it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket,
-                             erase_data, &str_set, proto);
+                             erase_data, dumpLatency, &str_set, proto);
 
     // Fill in UidMap if there is at least one metric to report.
     // This skips the uid map if it's an empty config.
@@ -492,7 +497,7 @@
         }
     }
     if (configKeysTtlExpired.size() > 0) {
-        WriteDataToDiskLocked(CONFIG_RESET);
+        WriteDataToDiskLocked(CONFIG_RESET, NO_TIME_CONSTRAINTS);
         resetConfigsLocked(timestampNs, configKeysTtlExpired);
     }
 }
@@ -501,7 +506,8 @@
     std::lock_guard<std::mutex> lock(mMetricsMutex);
     auto it = mMetricsManagers.find(key);
     if (it != mMetricsManagers.end()) {
-        WriteDataToDiskLocked(key, getElapsedRealtimeNs(), CONFIG_REMOVED);
+        WriteDataToDiskLocked(key, getElapsedRealtimeNs(), CONFIG_REMOVED, 
+                              NO_TIME_CONSTRAINTS);
         mMetricsManagers.erase(it);
         mUidMap->OnConfigRemoved(key);
     }
@@ -572,14 +578,15 @@
 
 void StatsLogProcessor::WriteDataToDiskLocked(const ConfigKey& key,
                                               const int64_t timestampNs,
-                                              const DumpReportReason dumpReportReason) {
+                                              const DumpReportReason dumpReportReason,
+                                              const DumpLatency dumpLatency) {
     if (mMetricsManagers.find(key) == mMetricsManagers.end() ||
         !mMetricsManagers.find(key)->second->shouldWriteToDisk()) {
         return;
     }
     ProtoOutputStream proto;
     onConfigMetricsReportLocked(key, timestampNs, true /* include_current_partial_bucket*/,
-                                true /* erase_data */, dumpReportReason, &proto);
+                                true /* erase_data */, dumpReportReason, dumpLatency, &proto);
     string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
          (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
     android::base::unique_fd fd(open(file_name.c_str(),
@@ -658,7 +665,8 @@
     StorageManager::deleteFile(file_name.c_str());
 }
 
-void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) {
+void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
+                                              const DumpLatency dumpLatency) {
     const int64_t timeNs = getElapsedRealtimeNs();
     // Do not write to disk if we already have in the last few seconds.
     // This is to avoid overwriting files that would have the same name if we
@@ -671,13 +679,14 @@
     }
     mLastWriteTimeNs = timeNs;
     for (auto& pair : mMetricsManagers) {
-        WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason);
+        WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason, dumpLatency);
     }
 }
 
-void StatsLogProcessor::WriteDataToDisk(const DumpReportReason dumpReportReason) {
+void StatsLogProcessor::WriteDataToDisk(const DumpReportReason dumpReportReason, 
+                                        const DumpLatency dumpLatency) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
-    WriteDataToDiskLocked(dumpReportReason);
+    WriteDataToDiskLocked(dumpReportReason, dumpLatency);
 }
 
 void StatsLogProcessor::informPullAlarmFired(const int64_t timestampNs) {
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index ea9c6e7..e92b897 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -66,10 +66,14 @@
 
     void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
                       const bool include_current_partial_bucket, const bool erase_data,
-                      const DumpReportReason dumpReportReason, vector<uint8_t>* outData);
+                      const DumpReportReason dumpReportReason, 
+                      const DumpLatency dumpLatency,
+                      vector<uint8_t>* outData);
     void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
                       const bool include_current_partial_bucket, const bool erase_data,
-                      const DumpReportReason dumpReportReason, ProtoOutputStream* proto);
+                      const DumpReportReason dumpReportReason,
+                      const DumpLatency dumpLatency,
+                      ProtoOutputStream* proto);
 
     /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
     void onAnomalyAlarmFired(
@@ -82,7 +86,8 @@
             unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
 
     /* Flushes data to disk. Data on memory will be gone after written to disk. */
-    void WriteDataToDisk(const DumpReportReason dumpReportReason);
+    void WriteDataToDisk(const DumpReportReason dumpReportReason,
+                         const DumpLatency dumpLatency);
 
     /* Persist metric activation status onto disk. */
     void WriteMetricsActivationToDisk(int64_t currentTimeNs);
@@ -153,14 +158,17 @@
 
     void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
 
-    void WriteDataToDiskLocked(const DumpReportReason dumpReportReason);
+    void WriteDataToDiskLocked(const DumpReportReason dumpReportReason,
+                               const DumpLatency dumpLatency);
     void WriteDataToDiskLocked(const ConfigKey& key, const int64_t timestampNs,
-                               const DumpReportReason dumpReportReason);
+                               const DumpReportReason dumpReportReason,
+                               const DumpLatency dumpLatency);
 
     void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
                                      const bool include_current_partial_bucket,
                                      const bool erase_data,
                                      const DumpReportReason dumpReportReason,
+                                     const DumpLatency dumpLatency,
                                      util::ProtoOutputStream* proto);
 
     /* Check if we should send a broadcast if approaching memory limits and if we're over, we
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index c542b62..4deb8bd 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -313,7 +313,9 @@
                 proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS_LIST);
         mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
                                  true /* includeCurrentBucket */, false /* erase_data */,
-                                 ADB_DUMP, &proto);
+                                 ADB_DUMP,
+                                 FAST,
+                                 &proto);
         proto.end(reportsListToken);
         proto.flush(out);
         proto.clear();
@@ -694,7 +696,9 @@
         if (good) {
             vector<uint8_t> data;
             mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
-                                     includeCurrentBucket, eraseData, ADB_DUMP, &data);
+                                     includeCurrentBucket, eraseData, ADB_DUMP,
+                                     NO_TIME_CONSTRAINTS,
+                                     &data);
             if (proto) {
                 for (size_t i = 0; i < data.size(); i ++) {
                     dprintf(out, "%c", data[i]);
@@ -758,7 +762,7 @@
 
 status_t StatsService::cmd_write_data_to_disk(int out) {
     dprintf(out, "Writing data to disk\n");
-    mProcessor->WriteDataToDisk(ADB_DUMP);
+    mProcessor->WriteDataToDisk(ADB_DUMP, NO_TIME_CONSTRAINTS);
     return NO_ERROR;
 }
 
@@ -958,7 +962,7 @@
 Status StatsService::informDeviceShutdown() {
     ENFORCE_UID(AID_SYSTEM);
     VLOG("StatsService::informDeviceShutdown");
-    mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN);
+    mProcessor->WriteDataToDisk(DEVICE_SHUTDOWN, FAST);
     mProcessor->WriteMetricsActivationToDisk(getElapsedRealtimeNs());
     return Status::ok();
 }
@@ -1000,7 +1004,7 @@
 void StatsService::Terminate() {
     ALOGI("StatsService::Terminating");
     if (mProcessor != nullptr) {
-        mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED);
+        mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED, FAST);
     }
 }
 
@@ -1017,8 +1021,10 @@
     IPCThreadState* ipc = IPCThreadState::self();
     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
     ConfigKey configKey(ipc->getCallingUid(), key);
+    // The dump latency does not matter here since we do not include the current bucket, we do not
+    // need to pull any new data anyhow.
     mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/,
-                             true /* erase_data */, GET_DATA_CALLED, output);
+                             true /* erase_data */, GET_DATA_CALLED, FAST, output);
     return Status::ok();
 }
 
@@ -1312,7 +1318,7 @@
     StatsdStats::getInstance().noteSystemServerRestart(getWallClockSec());
     if (mProcessor != nullptr) {
         ALOGW("Reset statsd upon system server restarts.");
-        mProcessor->WriteDataToDisk(STATSCOMPANION_DIED);
+        mProcessor->WriteDataToDisk(STATSCOMPANION_DIED, FAST);
         mProcessor->resetConfigs();
     }
     mAnomalyAlarmMonitor->setStatsCompanionService(nullptr);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d78647e..62926cb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5630,7 +5630,7 @@
  *   frameworks/base/packages/SystemUI/
  */
 message AssistGestureStageReported {
-  optional android.hardware.sensor.assist.AssistGestureStageEnum gesture_stage = 1;
+    optional android.hardware.sensor.assist.AssistGestureStageEnum gesture_stage = 1;
 }
 
 /**
@@ -5640,8 +5640,8 @@
  *   frameworks/base/packages/SystemUI/
  */
 message AssistGestureFeedbackReported {
-  // Whether or not the gesture was used.
-  optional android.hardware.sensor.assist.AssistGestureFeedbackEnum feedback_type = 1;
+    // Whether or not the gesture was used.
+    optional android.hardware.sensor.assist.AssistGestureFeedbackEnum feedback_type = 1;
 }
 
 /**
@@ -5651,8 +5651,8 @@
  *   frameworks/base/packages/SystemUI/
  */
 message AssistGestureProgressReported {
-  // [0,100] progress for the assist gesture.
-  optional int32 progress = 1;
+    // [0,100] progress for the assist gesture.
+    optional int32 progress = 1;
 }
 
 /*
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index e84f88d..96d1447 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -139,13 +139,13 @@
 
 
 void CountMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
-    flushIfNeededLocked(dumpTimeNs);
     mPastBuckets.clear();
 }
 
 void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
                                              const bool erase_data,
+                                             const DumpLatency dumpLatency,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     if (include_current_partial_bucket) {
@@ -319,7 +319,7 @@
         return;
     }
 
-    flushCurrentBucketLocked(eventTimeNs);
+    flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
     // Setup the bucket start time and number.
     int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
     mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
@@ -328,7 +328,8 @@
          (long long)mCurrentBucketStartTimeNs);
 }
 
-void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void CountMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                                   const int64_t& nextBucketStartTimeNs) {
     int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
     CountBucket info;
     info.mBucketStartNs = mCurrentBucketStartTimeNs;
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 1ac44264..b4a910c 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -57,6 +57,7 @@
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
                             const bool erase_data,
+                            const DumpLatency dumpLatency,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
 
@@ -78,7 +79,8 @@
     // Util function to flush the old packet.
     void flushIfNeededLocked(const int64_t& newEventTime) override;
 
-    void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                  const int64_t& nextBucketStartTimeNs) override;
 
     std::unordered_map<MetricDimensionKey, std::vector<CountBucket>> mPastBuckets;
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index da6b97c..5e4594b 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -456,6 +456,7 @@
 void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                                 const bool include_current_partial_bucket,
                                                 const bool erase_data,
+                                                const DumpLatency dumpLatency,
                                                 std::set<string> *str_set,
                                                 ProtoOutputStream* protoOutput) {
     if (include_current_partial_bucket) {
@@ -581,7 +582,8 @@
     mCurrentBucketNum += numBucketsForward;
 }
 
-void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void DurationMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                                      const int64_t& nextBucketStartTimeNs) {
     for (auto whatIt = mCurrentSlicedDurationTrackerMap.begin();
             whatIt != mCurrentSlicedDurationTrackerMap.end();) {
         for (auto it = whatIt->second.begin(); it != whatIt->second.end();) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index ec561b5..f711df2 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -64,6 +64,7 @@
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
                             const bool erase_data,
+                            const DumpLatency dumpLatency,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
 
@@ -88,7 +89,8 @@
     // Util function to flush the old packet.
     void flushIfNeededLocked(const int64_t& eventTime);
 
-    void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                  const int64_t& nextBucketStartTimeNs) override;
 
     const DurationMetric_AggregationType mAggregationType;
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 3b4af65..5435c84 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -108,6 +108,7 @@
 void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
                                              const bool erase_data,
+                                             const DumpLatency dumpLatency,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 96adfdd..74e6bc8 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -48,6 +48,7 @@
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
                             const bool erase_data,
+                            const DumpLatency dumpLatency,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 6301793..7b001b3 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -184,6 +184,7 @@
 void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
                                              const bool erase_data,
+                                             const DumpLatency dumpLatency,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     VLOG("Gauge metric %lld report now...", (long long)mMetricId);
@@ -528,7 +529,7 @@
         return;
     }
 
-    flushCurrentBucketLocked(eventTimeNs);
+    flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
 
     // Adjusts the bucket start and end times.
     int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
@@ -538,7 +539,8 @@
          (long long)mCurrentBucketStartTimeNs);
 }
 
-void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void GaugeMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                                   const int64_t& nextBucketStartTimeNs) {
     int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
 
     GaugeBucket info;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 64a1833..9b99fb1 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -82,8 +82,7 @@
             // Flush full buckets on the normal path up to the latest bucket boundary.
             flushIfNeededLocked(eventTimeNs);
         }
-        flushCurrentBucketLocked(eventTimeNs);
-        mCurrentBucketStartTimeNs = eventTimeNs;
+        flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
         if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
             pullAndMatchEventsLocked(eventTimeNs);
         }
@@ -99,6 +98,7 @@
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
                             const bool erase_data,
+                            const DumpLatency dumpLatency,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
@@ -119,7 +119,8 @@
     // Util function to flush the old packet.
     void flushIfNeededLocked(const int64_t& eventTime) override;
 
-    void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                  const int64_t& nextBucketStartTimeNs) override;
 
     void pullAndMatchEventsLocked(const int64_t timestampNs);
 
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 8ab3b06..99cb5d4 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -46,6 +46,16 @@
     kActiveOnBoot = 2,
 };
 
+enum DumpLatency {
+    // In some cases, we only have a short time range to do the dump, e.g. statsd is being killed.
+    // We might be able to return all the data in this mode. For instance, pull metrics might need
+    // to be pulled when the current bucket is requested.
+    FAST = 1,
+    // In other cases, it is fine for a dump to take more than a few milliseconds, e.g. config
+    // updates.
+    NO_TIME_CONSTRAINTS = 2
+};
+
 // A MetricProducer is responsible for compute one single metrics, creating stats log report, and
 // writing the report to dropbox. MetricProducers should respond to package changes as required in
 // PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
@@ -87,8 +97,7 @@
             flushIfNeededLocked(eventTimeNs);
         }
         // Now flush a partial bucket.
-        flushCurrentBucketLocked(eventTimeNs);
-        mCurrentBucketStartTimeNs = eventTimeNs;
+        flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
         // Don't update the current bucket number so that the anomaly tracker knows this bucket
         // is a partial bucket and can merge it with the previous bucket.
     };
@@ -135,11 +144,12 @@
     void onDumpReport(const int64_t dumpTimeNs,
                       const bool include_current_partial_bucket,
                       const bool erase_data,
+                      const DumpLatency dumpLatency,
                       std::set<string> *str_set,
                       android::util::ProtoOutputStream* protoOutput) {
         std::lock_guard<std::mutex> lock(mMutex);
         return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, erase_data,
-                str_set, protoOutput);
+                dumpLatency, str_set, protoOutput);
     }
 
     void clearPastBuckets(const int64_t dumpTimeNs) {
@@ -239,6 +249,7 @@
     virtual void onDumpReportLocked(const int64_t dumpTimeNs,
                                     const bool include_current_partial_bucket,
                                     const bool erase_data,
+                                    const DumpLatency dumpLatency,
                                     std::set<string> *str_set,
                                     android::util::ProtoOutputStream* protoOutput) = 0;
     virtual void clearPastBucketsLocked(const int64_t dumpTimeNs) = 0;
@@ -270,7 +281,7 @@
      */
     virtual void flushLocked(const int64_t& eventTimeNs) {
         flushIfNeededLocked(eventTimeNs);
-        flushCurrentBucketLocked(eventTimeNs);
+        flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
     };
 
     /**
@@ -283,7 +294,8 @@
      * flushIfNeededLocked or the app upgrade handler; the caller MUST update the bucket timestamp
      * and bucket number as needed.
      */
-    virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs){};
+    virtual void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                          const int64_t& nextBucketStartTimeNs) {};
 
     // Convenience to compute the current bucket's end time, which is always aligned with the
     // start time of the metric.
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 4851a8d..4b3bfd3 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -217,6 +217,7 @@
 void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
                                   const bool include_current_partial_bucket,
                                   const bool erase_data,
+                                  const DumpLatency dumpLatency,
                                   std::set<string> *str_set,
                                   ProtoOutputStream* protoOutput) {
     VLOG("=========================Metric Reports Start==========================");
@@ -227,10 +228,10 @@
                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
             if (mHashStringsInReport) {
                 producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
-                                       str_set, protoOutput);
+                                       dumpLatency, str_set, protoOutput);
             } else {
                 producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
-                                       nullptr, protoOutput);
+                                       dumpLatency, nullptr, protoOutput);
             }
             protoOutput->end(token);
         } else {
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index eab1f76..3904460 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -121,6 +121,7 @@
     virtual void onDumpReport(const int64_t dumpTimeNs,
                               const bool include_current_partial_bucket,
                               const bool erase_data,
+                              const DumpLatency dumpLatency,
                               std::set<string> *str_set,
                               android::util::ProtoOutputStream* protoOutput);
 
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 3cf378d..e94b75c 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -188,13 +188,28 @@
 void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
                                              const bool erase_data,
+                                             const DumpLatency dumpLatency,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     VLOG("metric %lld dump report now...", (long long)mMetricId);
+    flushIfNeededLocked(dumpTimeNs);
     if (include_current_partial_bucket) {
-        flushLocked(dumpTimeNs);
-    } else {
-        flushIfNeededLocked(dumpTimeNs);
+        // For pull metrics, we need to do a pull at bucket boundaries. If we do not do that the
+        // current bucket will have incomplete data and the next will have the wrong snapshot to do
+        // a diff against. If the condition is false, we are fine since the base data is reset and
+        // we are not tracking anything.
+        bool pullNeeded = mIsPulled && mCondition == ConditionState::kTrue;
+        if (pullNeeded) {
+            switch (dumpLatency) {
+                case FAST:
+                    invalidateCurrentBucket();
+                    break;
+                case NO_TIME_CONSTRAINTS:
+                    pullAndMatchEventsLocked(dumpTimeNs);
+                    break;
+            }
+        } 
+        flushCurrentBucketLocked(dumpTimeNs, dumpTimeNs);
     }
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
     protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked());
@@ -712,23 +727,21 @@
         return;
     }
 
-    flushCurrentBucketLocked(eventTimeNs);
-
     int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
-    mCurrentBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
-    mCurrentBucketNum += numBucketsForward;
+    int64_t nextBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
+    flushCurrentBucketLocked(eventTimeNs, nextBucketStartTimeNs);
 
+    mCurrentBucketNum += numBucketsForward;
     if (numBucketsForward > 1) {
         VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
         StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
         // take base again in future good bucket.
         resetBase();
     }
-    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
-         (long long)mCurrentBucketStartTimeNs);
 }
 
-void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs) {
+void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                                   const int64_t& nextBucketStartTimeNs) {
     if (mCondition == ConditionState::kUnknown) {
         StatsdStats::getInstance().noteBucketUnknownCondition(mMetricId);
     }
@@ -758,6 +771,9 @@
     }
     initCurrentSlicedBucket();
     mCurrentBucketIsInvalid = false;
+    mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
+    VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+         (long long)mCurrentBucketStartTimeNs);
 }
 
 ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index f26ad85..696d4fa 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -65,8 +65,7 @@
         if (mIsPulled && mCondition) {
             pullAndMatchEventsLocked(eventTimeNs - 1);
         }
-        flushCurrentBucketLocked(eventTimeNs);
-        mCurrentBucketStartTimeNs = eventTimeNs;
+        flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
     };
 
 protected:
@@ -79,6 +78,7 @@
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
                             const bool erase_data,
+                            const DumpLatency dumpLatency,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
@@ -97,7 +97,8 @@
     // Util function to flush the old packet.
     void flushIfNeededLocked(const int64_t& eventTime) override;
 
-    void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
+    void flushCurrentBucketLocked(const int64_t& eventTimeNs,
+                                  const int64_t& nextBucketStartTimeNs) override;
 
     void dropDataLocked(const int64_t dropTimeNs) override;
 
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 4579ca6..88aa180 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -173,7 +173,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
@@ -204,7 +204,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
@@ -235,7 +235,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, FAST, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
@@ -269,21 +269,21 @@
     ConfigMetricsReportList output;
 
     // Dump report WITHOUT erasing data.
-    processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, &bytes);
+    processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
     output.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(output.reports_size(), 1);
     EXPECT_EQ(output.reports(0).metrics_size(), 1);
     EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
 
     // Dump report WITH erasing data. There should be data since we didn't previously erase it.
-    processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, &bytes);
+    processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
     output.ParseFromArray(bytes.data(), bytes.size());
     EXPECT_EQ(output.reports_size(), 1);
     EXPECT_EQ(output.reports(0).metrics_size(), 1);
     EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
 
     // Dump report again. There should be no data since we erased it.
-    processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, &bytes);
+    processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
     output.ParseFromArray(bytes.data(), bytes.size());
     // We don't care whether statsd has a report, as long as it has no count metrics in it.
     bool noData = output.reports_size() == 0
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a9841c9..3382525 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -147,7 +147,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -295,7 +295,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index a8914da..e4186b7 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -212,7 +212,7 @@
                 ConfigMetricsReportList reports;
                 vector<uint8_t> buffer;
                 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                        true, ADB_DUMP, &buffer);
+                                        true, ADB_DUMP, FAST, &buffer);
                 EXPECT_TRUE(buffer.size() > 0);
                 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
                 backfillDimensionPath(&reports);
@@ -548,7 +548,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    true, ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, FAST, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -798,7 +798,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    true, ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, FAST, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index 621b6ed..f3ecd56 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -131,7 +131,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -347,7 +347,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -531,7 +531,7 @@
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
         processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                                ADB_DUMP, &buffer);
+                                ADB_DUMP, FAST, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
@@ -733,7 +733,7 @@
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
         processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                                ADB_DUMP, &buffer);
+                                ADB_DUMP, FAST, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index 9f8acaf..489bb0b 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -143,7 +143,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    true, ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, FAST, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -438,7 +438,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    true, ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, FAST, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -659,7 +659,7 @@
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
         processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                                ADB_DUMP, &buffer);
+                                ADB_DUMP, FAST, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 24a9980..946eccf 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -125,7 +125,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -248,7 +248,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -352,7 +352,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 3af8212..cd80310 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -150,7 +150,7 @@
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
         processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
-                                ADB_DUMP, &buffer);
+                                ADB_DUMP, FAST, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index 85d8a56..7fb43f8a 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -211,7 +211,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 9349c85..78fb391 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -200,7 +200,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -319,7 +319,7 @@
     vector<uint8_t> buffer;
 
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index aee0c1f..ef3643f 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -46,7 +46,7 @@
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), kConfigKey);
     processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
-                            true /* erase_data */, ADB_DUMP, &output);
+                            true /* erase_data */, ADB_DUMP, FAST, &output);
     ConfigMetricsReportList reports;
     reports.ParseFromArray(output.data(), output.size());
     EXPECT_EQ(1, reports.reports_size());
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index f3c4e12..cdb5a78 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -121,7 +121,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -228,7 +228,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index 16be3d7..e13bf14 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -128,7 +128,7 @@
     vector<uint8_t> buffer;
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -165,7 +165,7 @@
     vector<uint8_t> buffer;
     ConfigMetricsReportList reports;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -216,7 +216,7 @@
     }
 
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -249,7 +249,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
 
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -279,7 +279,7 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -325,7 +325,7 @@
     }
 
     processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, &buffer);
+                            ADB_DUMP, FAST, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 7e7ffed..a9d2c88 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -2797,7 +2797,6 @@
     EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
 }
 
-
 TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
     ValueMetric metric;
     metric.set_id(metricId);
@@ -2864,6 +2863,187 @@
     EXPECT_EQ(true, valueProducer.mHasGlobalBase);
 }
 
+static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
+    vector<uint8_t> bytes;
+    bytes.resize(proto->size());
+    size_t pos = 0;
+    auto iter = proto->data();
+    while (iter.readBuffer() != NULL) {
+        size_t toRead = iter.currentToRead();
+        std::memcpy(&((bytes)[pos]), iter.readBuffer(), toRead);
+        pos += toRead;
+        iter.rp()->move(toRead);
+    }
+
+    StatsLogReport report;
+    report.ParseFromArray(bytes.data(), bytes.size());
+    return report;
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // Initial pull.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(1);
+                event->write(1);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer.onDumpReport(bucketStartTimeNs + 10, 
+                               true /* include recent buckets */, true,
+                               FAST, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    // Bucket is invalid since we did not pull when dump report was called.
+    EXPECT_EQ(0, report.value_metrics().data_size());
+}
+
+TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // Initial pull.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(1);
+                event->write(1);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(tagId);
+    event->write(2);
+    event->write(2);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer.onDumpReport(bucket4StartTimeNs, 
+                               false /* include recent buckets */, true,
+                               FAST, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    // Previous bucket is part of the report.
+    EXPECT_EQ(1, report.value_metrics().data_size());
+    EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_max_pull_delay_sec(INT_MAX);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // Initial pull.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(tagId);
+                event->write(1);
+                event->write(1);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write(tagId);
+                event->write(3);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+                                      bucketStartTimeNs, pullerManager);
+
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer.onDumpReport(bucketStartTimeNs + 10, 
+                               true /* include recent buckets */, true,
+                               NO_TIME_CONSTRAINTS, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_EQ(1, report.value_metrics().data_size());
+    EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+}
+
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 1de8117..de378b0 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -398,8 +398,8 @@
             }
         }
 
-        /**
-         * See com.android.internal.os.SystemZygoteInit.readArgumentList()
+        /*
+         * See com.android.internal.os.ZygoteArguments.parseArgs()
          * Presently the wire format to the zygote process is:
          * a) a count of arguments (argc, in essence)
          * b) a number of newline-separated argument strings equal to count
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index ce83a57..792eda7 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -85,6 +85,18 @@
     private final IAugmentedAutofillService mInterface = new IAugmentedAutofillService.Stub() {
 
         @Override
+        public void onConnected() {
+            mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnConnected,
+                    AugmentedAutofillService.this));
+        }
+
+        @Override
+        public void onDisconnected() {
+            mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnDisconnected,
+                    AugmentedAutofillService.this));
+        }
+
+        @Override
         public void onFillRequest(int sessionId, IBinder client, int taskId,
                 ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
                 long requestTime, IFillCallback callback) {
@@ -174,6 +186,14 @@
     public void onDisconnected() {
     }
 
+    private void handleOnConnected() {
+        onConnected();
+    }
+
+    private void handleOnDisconnected() {
+        onDisconnected();
+    }
+
     private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
             @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
             @Nullable AutofillValue focusedValue, long requestTime,
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
index fb6912a..5096811 100644
--- a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -31,7 +31,8 @@
  * @hide
  */
 oneway interface IAugmentedAutofillService {
-
+    void onConnected();
+    void onDisconnected();
     void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
                        in ComponentName activityComponent, in AutofillId focusedId,
                        in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
diff --git a/core/java/android/view/CompositionSamplingListener.java b/core/java/android/view/CompositionSamplingListener.java
new file mode 100644
index 0000000..e4309a6
--- /dev/null
+++ b/core/java/android/view/CompositionSamplingListener.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.graphics.Rect;
+import android.os.IBinder;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Listener for sampling the result of the screen composition.
+ * {@hide}
+ */
+public abstract class CompositionSamplingListener {
+
+    private final long mNativeListener;
+    private final Executor mExecutor;
+
+    public CompositionSamplingListener(Executor executor) {
+        mExecutor = executor;
+        mNativeListener = nativeCreate(this);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mNativeListener != 0) {
+                unregister(this);
+                nativeDestroy(mNativeListener);
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Reports a luma sample from the registered region.
+     */
+    public abstract void onSampleCollected(float medianLuma);
+
+    /**
+     * Registers a sampling listener.
+     */
+    public static void register(CompositionSamplingListener listener,
+            int displayId, IBinder stopLayer, Rect samplingArea) {
+        Preconditions.checkArgument(displayId == Display.DEFAULT_DISPLAY,
+                "default display only for now");
+        nativeRegister(listener.mNativeListener, stopLayer, samplingArea.left, samplingArea.top,
+                samplingArea.right, samplingArea.bottom);
+    }
+
+    /**
+     * Unregisters a sampling listener.
+     */
+    public static void unregister(CompositionSamplingListener listener) {
+        nativeUnregister(listener.mNativeListener);
+    }
+
+    /**
+     * Dispatch the collected sample.
+     *
+     * Called from native code on a binder thread.
+     */
+    private static void dispatchOnSampleCollected(CompositionSamplingListener listener,
+            float medianLuma) {
+        listener.mExecutor.execute(() -> listener.onSampleCollected(medianLuma));
+    }
+
+    private static native long nativeCreate(CompositionSamplingListener thiz);
+    private static native void nativeDestroy(long ptr);
+    private static native void nativeRegister(long ptr, IBinder stopLayer,
+            int samplingAreaLeft, int top, int right, int bottom);
+    private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index a6b40ed..e9b1683 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -369,6 +369,11 @@
     public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES =
             "smart_suggestion_supported_modes";
 
+    /** @hide */
+    public static final int RESULT_OK = 0;
+    /** @hide */
+    public static final int RESULT_CODE_NOT_SERVICE = -1;
+
     /**
      * Makes an authentication id from a request id and a dataset id.
      *
@@ -1789,7 +1794,11 @@
     @Deprecated
     public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
             @Nullable List<ComponentName> activities) {
-        // TODO(b/123100824): implement
+        setAugmentedAutofillWhitelist(toSet(packages), toSet(activities));
+    }
+
+    private <T> ArraySet<T> toSet(@Nullable List<T> set) {
+        return set == null ? null : new ArraySet<T>(set);
     }
 
     /**
@@ -1814,7 +1823,32 @@
     @TestApi
     public void setAugmentedAutofillWhitelist(@Nullable Set<String> packages,
             @Nullable Set<ComponentName> activities) {
-        // TODO(b/123100824): implement
+        if (!hasAutofillFeature()) {
+            return;
+        }
+
+        final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
+        final int resultCode;
+        try {
+            mService.setAugmentedAutofillWhitelist(toList(packages), toList(activities),
+                    resultReceiver);
+            resultCode = resultReceiver.getIntResult();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        switch (resultCode) {
+            case RESULT_OK:
+                return;
+            case RESULT_CODE_NOT_SERVICE:
+                throw new SecurityException("caller is not user's Augmented Autofill Service");
+            default:
+                Log.wtf(TAG, "setAugmentedAutofillWhitelist(): received invalid result: "
+                        + resultCode);
+        }
+    }
+
+    private <T> ArrayList<T> toList(@Nullable Set<T> set) {
+        return set == null ? null : new ArrayList<T>(set);
     }
 
     private void requestShowFillUi(int sessionId, AutofillId id, int width, int height,
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 26aeba5..9e6a4af 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -63,4 +63,6 @@
     void getAutofillServiceComponentName(in IResultReceiver result);
     void getAvailableFieldClassificationAlgorithms(in IResultReceiver result);
     void getDefaultFieldClassificationAlgorithm(in IResultReceiver result);
+    void setAugmentedAutofillWhitelist(in List<String> packages, in List<ComponentName> activities,
+        in IResultReceiver result);
 }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 22884ac..0604ab2 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -767,17 +767,6 @@
      * @throws IOException passed straight through
      */
     static String[] readArgumentList(BufferedReader socketReader) throws IOException {
-
-        /**
-         * See android.os.Process.zygoteSendArgsAndGetPid()
-         * Presently the wire format to the zygote process is:
-         * a) a count of arguments (argc, in essence)
-         * b) a number of newline-separated argument strings equal to count
-         *
-         * After the zygote process reads these it will write the pid of
-         * the child or -1 on failure.
-         */
-
         int argc;
 
         try {
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index e6bcd37..c24a9e0 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -217,8 +217,17 @@
      * Per security review bug #1112214, duplicate args are disallowed in critical cases to make
      * injection harder.
      */
-    private void parseArgs(String[] args)
-            throws IllegalArgumentException {
+    private void parseArgs(String[] args) throws IllegalArgumentException {
+        /*
+         * See android.os.ZygoteProcess.zygoteSendArgsAndGetResult()
+         * Presently the wire format to the zygote process is:
+         * a) a count of arguments (argc, in essence)
+         * b) a number of newline-separated argument strings equal to count
+         *
+         * After the zygote process reads these it will write the pid of
+         * the child or -1 on failure.
+         */
+
         int curArg = 0;
 
         boolean seenRuntimeArgs = false;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 30e9937..c309f27 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -62,6 +62,7 @@
         "android_graphics_drawable_AnimatedVectorDrawable.cpp",
         "android_graphics_drawable_VectorDrawable.cpp",
         "android_graphics_Picture.cpp",
+        "android_view_CompositionSamplingListener.cpp",
         "android_view_DisplayEventReceiver.cpp",
         "android_view_DisplayListCanvas.cpp",
         "android_view_TextureLayer.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 019ade9..0938e56 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -163,6 +163,7 @@
 extern int register_android_view_Surface(JNIEnv* env);
 extern int register_android_view_SurfaceControl(JNIEnv* env);
 extern int register_android_view_SurfaceSession(JNIEnv* env);
+extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
 extern int register_android_view_ThreadedRenderer(JNIEnv* env);
 extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env);
@@ -1415,6 +1416,7 @@
     REG_JNI(register_android_view_Surface),
     REG_JNI(register_android_view_SurfaceControl),
     REG_JNI(register_android_view_SurfaceSession),
+    REG_JNI(register_android_view_CompositionSamplingListener),
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
diff --git a/core/jni/android_view_CompositionSamplingListener.cpp b/core/jni/android_view_CompositionSamplingListener.cpp
new file mode 100644
index 0000000..283ba0d
--- /dev/null
+++ b/core/jni/android_view_CompositionSamplingListener.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CompositionSamplingListener"
+
+#include "android_util_Binder.h"
+
+#include <nativehelper/JNIHelp.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <binder/IServiceManager.h>
+
+#include <gui/IRegionSamplingListener.h>
+#include <gui/ISurfaceComposer.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+namespace {
+
+struct {
+    jclass mClass;
+    jmethodID mDispatchOnSampleCollected;
+} gListenerClassInfo;
+
+struct CompositionSamplingListener : public BnRegionSamplingListener {
+    CompositionSamplingListener(JNIEnv* env, jobject listener)
+            : mListener(env->NewGlobalRef(listener)) {}
+
+    void onSampleCollected(float medianLuma) override {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onSampleCollected.");
+
+        env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+                gListenerClassInfo.mDispatchOnSampleCollected, mListener,
+                static_cast<jfloat>(medianLuma));
+        if (env->ExceptionCheck()) {
+            ALOGE("CompositionSamplingListener.onSampleCollected() failed.");
+            LOGE_EX(env);
+            env->ExceptionClear();
+        }
+    }
+
+protected:
+    virtual ~CompositionSamplingListener() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteGlobalRef(mListener);
+    }
+
+private:
+    jobject mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+    CompositionSamplingListener* listener = new CompositionSamplingListener(env, obj);
+    listener->incStrong((void*)nativeCreate);
+    return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+    CompositionSamplingListener* listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+    listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jobject stopLayerTokenObj,
+        jint left, jint top, jint right, jint bottom) {
+    sp<CompositionSamplingListener> listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+    sp<IBinder> stopLayerHandle = ibinderForJavaObject(env, stopLayerTokenObj);
+
+    // TODO: Use SurfaceComposerClient once it has addRegionSamplingListener.
+    sp<ISurfaceComposer> composer;
+    if (getService(String16("SurfaceFlinger"), &composer) != NO_ERROR) {
+        jniThrowRuntimeException(env, "Couldn't retrieve SurfaceFlinger");
+        return;
+    }
+
+    composer->addRegionSamplingListener(
+            Rect(left, top, right, bottom), stopLayerHandle, listener);
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<CompositionSamplingListener> listener = reinterpret_cast<CompositionSamplingListener*>(ptr);
+
+    // TODO: Use SurfaceComposerClient once it has addRegionSamplingListener.
+    sp<ISurfaceComposer> composer;
+    if (getService(String16("SurfaceFlinger"), &composer) != NO_ERROR) {
+        jniThrowRuntimeException(env, "Couldn't retrieve SurfaceFlinger");
+        return;
+    }
+
+    composer->removeRegionSamplingListener(listener);
+}
+
+const JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeCreate", "(Landroid/view/CompositionSamplingListener;)J",
+            (void*)nativeCreate },
+    { "nativeDestroy", "(J)V",
+            (void*)nativeDestroy },
+    { "nativeRegister", "(JLandroid/os/IBinder;IIII)V",
+            (void*)nativeRegister },
+    { "nativeUnregister", "(J)V",
+            (void*)nativeUnregister }
+};
+
+} // namespace
+
+int register_android_view_CompositionSamplingListener(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/view/CompositionSamplingListener",
+            gMethods, NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz = env->FindClass("android/view/CompositionSamplingListener");
+    gListenerClassInfo.mDispatchOnSampleCollected = env->GetStaticMethodID(
+            clazz, "dispatchOnSampleCollected", "(Landroid/view/CompositionSamplingListener;F)V");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/proto/android/hardware/sensor/assist/enums.proto b/core/proto/android/hardware/sensor/assist/enums.proto
index 8c5841a..012dcb2 100644
--- a/core/proto/android/hardware/sensor/assist/enums.proto
+++ b/core/proto/android/hardware/sensor/assist/enums.proto
@@ -21,14 +21,14 @@
 option java_multiple_files = true;
 
 enum AssistGestureStageEnum {
-  ASSIST_GESTURE_STAGE_UNKNOWN = 0;
-  ASSIST_GESTURE_STAGE_PROGRESS = 1;
-  ASSIST_GESTURE_STAGE_PRIMED = 2;
-  ASSIST_GESTURE_STAGE_DETECTED = 3;
+    ASSIST_GESTURE_STAGE_UNKNOWN = 0;
+    ASSIST_GESTURE_STAGE_PROGRESS = 1;
+    ASSIST_GESTURE_STAGE_PRIMED = 2;
+    ASSIST_GESTURE_STAGE_DETECTED = 3;
 }
 
 enum AssistGestureFeedbackEnum {
-  ASSIST_GESTURE_FEEDBACK_UNKNOWN = 0;
-  ASSIST_GESTURE_FEEDBACK_NOT_USED = 1;
-  ASSIST_GESTURE_FEEDBACK_USED = 2;
+    ASSIST_GESTURE_FEEDBACK_UNKNOWN = 0;
+    ASSIST_GESTURE_FEEDBACK_NOT_USED = 1;
+    ASSIST_GESTURE_FEEDBACK_USED = 2;
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java b/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java
new file mode 100644
index 0000000..75a2e8a
--- /dev/null
+++ b/core/tests/coretests/src/android/view/CompositionSamplingListenerTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.graphics.Rect;
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class CompositionSamplingListenerTest {
+
+    @Test
+    public void testRegisterUnregister() {
+        CompositionSamplingListener.register(mListener, DEFAULT_DISPLAY, new Binder(),
+                new Rect(1, 1, 10, 10));
+        CompositionSamplingListener.unregister(mListener);
+    }
+
+    private CompositionSamplingListener mListener = new CompositionSamplingListener(Runnable::run) {
+        @Override
+        public void onSampleCollected(float medianLuma) {
+            // Ignore
+        }
+    };
+}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f996d38..7de7f8f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3188,6 +3188,10 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
+        return registerAudioPolicyStatic(policy);
+    }
+
+    static int registerAudioPolicyStatic(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
         }
@@ -3214,6 +3218,10 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
+        unregisterAudioPolicyAsyncStatic(policy);
+    }
+
+    static void unregisterAudioPolicyAsyncStatic(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
         }
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
new file mode 100644
index 0000000..22f14ae
--- /dev/null
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioMixingRule;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Configuration for capturing audio played by other apps.
+ *
+ * <p>An example for creating a capture configuration for capturing all media playback:
+ *
+ * <pre>
+ *     AudioAttributes mediaAttr = new AudioAttributes.Builder()
+ *         .setUsage(AudioAttributes.USAGE_MEDIA)
+ *         .build();
+ *     AudioPlaybackCaptureConfiguration config = new AudioPlaybackCaptureConfiguration.Builder()
+ *         .addMatchingUsage(mediaAttr)
+ *         .build();
+ *     AudioRecord record = new AudioRecord.Builder()
+ *         .setPlaybackCaptureConfig(config)
+ *         .build();
+ * </pre>
+ *
+ * @see AudioRecord.Builder#setPlaybackCaptureConfig(AudioPlaybackCaptureConfiguration)
+ */
+public final class AudioPlaybackCaptureConfiguration {
+
+    private final AudioMixingRule mAudioMixingRule;
+
+    private AudioPlaybackCaptureConfiguration(AudioMixingRule audioMixingRule) {
+        mAudioMixingRule = audioMixingRule;
+    }
+
+    /**
+     * Returns a mix that routes audio back into the app while still playing it from the speakers.
+     *
+     * @param audioFormat The format in which to capture the audio.
+     */
+    AudioMix createAudioMix(AudioFormat audioFormat) {
+        return new AudioMix.Builder(mAudioMixingRule)
+                .setFormat(audioFormat)
+                .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER)
+                .build();
+    }
+
+    /** Builder for creating {@link AudioPlaybackCaptureConfiguration} instances. */
+    public static final class Builder {
+
+        private static final int MATCH_TYPE_UNSPECIFIED = 0;
+        private static final int MATCH_TYPE_INCLUSIVE = 1;
+        private static final int MATCH_TYPE_EXCLUSIVE = 2;
+
+        private static final String ERROR_MESSAGE_MISMATCHED_RULES =
+                "Inclusive and exclusive usage rules cannot be combined";
+
+        private final AudioMixingRule.Builder mAudioMixingRuleBuilder;
+        private int mUsageMatchType = MATCH_TYPE_UNSPECIFIED;
+        private int mUidMatchType = MATCH_TYPE_UNSPECIFIED;
+
+        public Builder() {
+            mAudioMixingRuleBuilder = new AudioMixingRule.Builder();
+        }
+
+        /**
+         * Only capture audio output with the given {@link AudioAttributes}.
+         *
+         * <p>If called multiple times, will capture audio output that matches any of the given
+         * attributes.
+         *
+         * @throws IllegalStateException if called in conjunction with
+         *     {@link #excludeUsage(AudioAttributes)}.
+         */
+        public Builder addMatchingUsage(@NonNull AudioAttributes audioAttributes) {
+            Preconditions.checkNotNull(audioAttributes);
+            Preconditions.checkState(
+                    mUsageMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder
+                    .addRule(audioAttributes, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+            mUsageMatchType = MATCH_TYPE_INCLUSIVE;
+            return this;
+        }
+
+        /**
+         * Only capture audio output by app with the matching {@code uid}.
+         *
+         * <p>If called multiple times, will capture audio output by apps whose uid is any of the
+         * given uids.
+         *
+         * @throws IllegalStateException if called in conjunction with {@link #excludeUid(int)}.
+         */
+        public Builder addMatchingUid(int uid) {
+            Preconditions.checkState(
+                    mUidMatchType != MATCH_TYPE_EXCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder.addMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
+            mUidMatchType = MATCH_TYPE_INCLUSIVE;
+            return this;
+        }
+
+        /**
+         * Only capture audio output that does not match the given {@link AudioAttributes}.
+         *
+         * <p>If called multiple times, will capture audio output that does not match any of the
+         * given attributes.
+         *
+         * @throws IllegalStateException if called in conjunction with
+         *     {@link #addMatchingUsage(AudioAttributes)}.
+         */
+        public Builder excludeUsage(@NonNull AudioAttributes audioAttributes) {
+            Preconditions.checkNotNull(audioAttributes);
+            Preconditions.checkState(
+                    mUsageMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder.excludeRule(audioAttributes,
+                    AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
+            mUsageMatchType = MATCH_TYPE_EXCLUSIVE;
+            return this;
+        }
+
+        /**
+         * Only capture audio output by apps that do not have the matching {@code uid}.
+         *
+         * <p>If called multiple times, will capture audio output by apps whose uid is not any of
+         * the given uids.
+         *
+         * @throws IllegalStateException if called in conjunction with {@link #addMatchingUid(int)}.
+         */
+        public Builder excludeUid(int uid) {
+            Preconditions.checkState(
+                    mUidMatchType != MATCH_TYPE_INCLUSIVE, ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder.excludeMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
+            mUidMatchType = MATCH_TYPE_EXCLUSIVE;
+            return this;
+        }
+
+        /**
+         * Builds the configuration instance.
+         *
+         * @throws UnsupportedOperationException if the parameters set are incompatible.
+         */
+        public AudioPlaybackCaptureConfiguration build() {
+            return new AudioPlaybackCaptureConfiguration(mAudioMixingRuleBuilder.build());
+        }
+    }
+}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 24a3a9b..10accf2 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -24,6 +24,8 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
+import android.media.audiopolicy.AudioMix;
+import android.media.audiopolicy.AudioPolicy;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -37,6 +39,7 @@
 import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -182,6 +185,8 @@
     //---------------------------------------------------------
     // Member variables
     //--------------------
+    private AudioPolicy mAudioCapturePolicy;
+
     /**
      * The audio data sampling rate in Hz.
      * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
@@ -429,6 +434,16 @@
     }
 
     /**
+     * Sets an {@link AudioPolicy} to automatically unregister when the record is released.
+     *
+     * <p>This is to prevent users of the audio capture API from having to manually unregister the
+     * policy that was used to create the record.
+     */
+    private void unregisterAudioPolicyOnRelease(AudioPolicy audioPolicy) {
+        mAudioCapturePolicy = audioPolicy;
+    }
+
+    /**
      * @hide
      */
     /* package */ void deferred_connect(long  nativeRecordInJavaObj) {
@@ -491,6 +506,11 @@
      * the minimum buffer size for the source is used.
      */
     public static class Builder {
+
+        private static final String ERROR_MESSAGE_SOURCE_MISMATCH =
+                "Cannot both set audio source and set playback capture config";
+
+        private AudioPlaybackCaptureConfiguration mAudioPlaybackCaptureConfiguration;
         private AudioAttributes mAttributes;
         private AudioFormat mFormat;
         private int mBufferSizeInBytes;
@@ -509,6 +529,9 @@
          * @throws IllegalArgumentException
          */
         public Builder setAudioSource(int source) throws IllegalArgumentException {
+            Preconditions.checkState(
+                    mAudioPlaybackCaptureConfiguration == null,
+                    ERROR_MESSAGE_SOURCE_MISMATCH);
             if ( (source < MediaRecorder.AudioSource.DEFAULT) ||
                     (source > MediaRecorder.getAudioSourceMax()) ) {
                 throw new IllegalArgumentException("Invalid audio source " + source);
@@ -578,6 +601,25 @@
         }
 
         /**
+         * Sets the {@link AudioRecord} to record audio played by other apps.
+         *
+         * @param config Defines what apps to record audio from (i.e., via either their uid or
+         *               the type of audio).
+         * @throws IllegalStateException if called in conjunction with {@link #setAudioSource(int)}.
+         * @throws NullPointerException if {@code config} is null.
+         */
+        public Builder setAudioPlaybackCaptureConfig(
+                @NonNull AudioPlaybackCaptureConfiguration config) {
+            Preconditions.checkNotNull(
+                    config, "Illegal null AudioPlaybackCaptureConfiguration argument");
+            Preconditions.checkState(
+                    mAttributes == null,
+                    ERROR_MESSAGE_SOURCE_MISMATCH);
+            mAudioPlaybackCaptureConfiguration = config;
+            return this;
+        }
+
+        /**
          * @hide
          * To be only used by system components.
          * @param sessionId ID of audio session the AudioRecord must be attached to, or
@@ -595,6 +637,15 @@
             return this;
         }
 
+        private AudioRecord buildAudioPlaybackCaptureRecord() {
+            AudioMix audioMix = mAudioPlaybackCaptureConfiguration.createAudioMix(mFormat);
+            AudioPolicy audioPolicy = new AudioPolicy.Builder(/*context=*/ null)
+                    .addMix(audioMix).build();
+            AudioRecord record = audioPolicy.createAudioRecordSink(audioMix);
+            record.unregisterAudioPolicyOnRelease(audioPolicy);
+            return record;
+        }
+
         /**
          * @return a new {@link AudioRecord} instance successfully initialized with all
          *     the parameters set on this <code>Builder</code>.
@@ -603,6 +654,10 @@
          *     or if the device was not available.
          */
         public AudioRecord build() throws UnsupportedOperationException {
+            if (mAudioPlaybackCaptureConfiguration != null) {
+                return buildAudioPlaybackCaptureRecord();
+            }
+
             if (mFormat == null) {
                 mFormat = new AudioFormat.Builder()
                         .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
@@ -757,6 +812,9 @@
         } catch(IllegalStateException ise) {
             // don't raise an exception, we're releasing the resources.
         }
+        if (mAudioCapturePolicy != null) {
+            AudioManager.unregisterAudioPolicyAsyncStatic(mAudioCapturePolicy);
+        }
         native_release();
         mState = STATE_UNINITIALIZED;
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
index 8077431..efa4387 100644
--- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
+++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
@@ -16,25 +16,21 @@
 
 package com.android.systemui.notifications;
 
+import android.app.ActivityManager;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.SuppressLint;
-import android.app.ActivityManager;
 import android.car.Car;
 import android.car.CarNotConnectedException;
 import android.car.drivingstate.CarUxRestrictionsManager;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.os.IBinder;
 import android.os.ServiceManager;
-import android.os.UserHandle;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.GestureDetector;
@@ -95,28 +91,12 @@
     private static int sSettleOpenPercentage;
     private static int sSettleClosePercentage;
 
-    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (action.equals(Intent.ACTION_USER_SWITCHED)) {
-                mCarNotificationListener.registerAsSystemService(mContext,
-                        mCarUxRestrictionManagerWrapper,
-                        mClickHandlerFactory);
-                inflateNotificationContent();
-            }
-        }
-    };
-
     /**
      * Inits the window that hosts the notifications and establishes the connections
      * to the car related services.
      */
     @Override
     public void start() {
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_USER_SWITCHED);
-        mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);
         sSettleOpenPercentage = mContext.getResources().getInteger(
                 R.integer.notification_settle_open_percentage);
         sSettleClosePercentage = mContext.getResources().getInteger(
@@ -133,11 +113,12 @@
                         ServiceManager.getService(Context.STATUS_BAR_SERVICE)),
                 launchResult -> {
                     if (launchResult == ActivityManager.START_TASK_TO_FRONT
-                            || launchResult == ActivityManager.START_SUCCESS) {
+                            || launchResult == ActivityManager.START_SUCCESS){
                         closeCarNotifications(DEFAULT_FLING_VELOCITY);
                     }
                 });
-
+        mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
+                mClickHandlerFactory);
         mCar = Car.createCar(mContext, mCarConnectionListener);
         mCar.connect();
         NotificationGestureListener gestureListener = new NotificationGestureListener();
@@ -150,6 +131,8 @@
         mCarNotificationWindow
                 .setBackgroundColor(mContext.getColor(R.color.notification_shade_background_color));
 
+        inflateNotificationContent();
+
         WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY,
@@ -220,7 +203,7 @@
         // There's a view installed at a higher z-order such that we can intercept the ACTION_DOWN
         // to set the initial click state.
         mCarNotificationWindow.findViewById(R.id.glass_pane).setOnTouchListener((v, event) -> {
-            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+            if (event.getActionMasked() == MotionEvent.ACTION_UP ) {
                 mNotificationListAtBottomAtTimeOfTouch = false;
             }
             if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -271,7 +254,7 @@
         public boolean onTouch(View v, MotionEvent event) {
             // reset mNotificationListAtBottomAtTimeOfTouch here since the "glass pane" will not
             // get the up event
-            if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+            if (event.getActionMasked() == MotionEvent.ACTION_UP ) {
                 mNotificationListAtBottomAtTimeOfTouch = false;
             }
             boolean wasScrolledUp = mScrollUpDetector.onTouchEvent(event);
@@ -355,7 +338,7 @@
         public boolean onFling(MotionEvent event1, MotionEvent event2,
                 float velocityX, float velocityY) {
             if (Math.abs(event1.getX() - event2.getX()) > SWIPE_MAX_OFF_PATH
-                    || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
+                    || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY){
                 // swipe was not vertical or was not fast enough
                 return false;
             }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index e6acfbe..39da194 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -51,7 +51,7 @@
      *               this method to avoid synchronization issues.
      */
     public void scheduleApply(final SyncRtSurfaceTransactionApplierCompat.SurfaceParams... params) {
-        if (mTargetViewRootImpl == null) {
+        if (mTargetViewRootImpl == null || mTargetViewRootImpl.getView() == null) {
             return;
         }
         mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 152b9fc..4d89a39 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -43,6 +43,8 @@
 
     static final String TAG = "DozeMachine";
     static final boolean DEBUG = DozeService.DEBUG;
+    private static final String REASON_CHANGE_STATE = "DozeMachine#requestState";
+    private static final String REASON_HELD_FOR_STATE = "DozeMachine#heldForState";
 
     public enum State {
         /** Default state. Transition to INITIALIZED to get Doze going. */
@@ -167,14 +169,14 @@
         boolean runNow = !isExecutingTransition();
         mQueuedRequests.add(requestedState);
         if (runNow) {
-            mWakeLock.acquire();
+            mWakeLock.acquire(REASON_CHANGE_STATE);
             for (int i = 0; i < mQueuedRequests.size(); i++) {
                 // Transitions in Parts can call back into requestState, which will
                 // cause mQueuedRequests to grow.
                 transitionTo(mQueuedRequests.get(i), pulseReason);
             }
             mQueuedRequests.clear();
-            mWakeLock.release();
+            mWakeLock.release(REASON_CHANGE_STATE);
         }
     }
 
@@ -311,10 +313,10 @@
     private void updateWakeLockState(State newState) {
         boolean staysAwake = newState.staysAwake();
         if (mWakeLockHeldForCurrentState && !staysAwake) {
-            mWakeLock.release();
+            mWakeLock.release(REASON_HELD_FOR_STATE);
             mWakeLockHeldForCurrentState = false;
         } else if (!mWakeLockHeldForCurrentState && staysAwake) {
-            mWakeLock.acquire();
+            mWakeLock.acquire(REASON_HELD_FOR_STATE);
             mWakeLockHeldForCurrentState = true;
         }
     }
@@ -336,6 +338,7 @@
     public void dump(PrintWriter pw) {
         pw.print(" state="); pw.println(mState);
         pw.print(" wakeLockHeldForCurrentState="); pw.println(mWakeLockHeldForCurrentState);
+        pw.print(" wakeLock="); pw.println(mWakeLock);
         pw.println("Parts:");
         for (Part p : mParts) {
             p.dump(pw);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index f14d396..368451a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -57,7 +57,7 @@
         mDozeService = service;
         mHandler = handler;
         mParameters = parameters;
-        mWakeLock = new SettableWakeLock(wakeLock);
+        mWakeLock = new SettableWakeLock(wakeLock, TAG);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index e207cb1..70bf903 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -348,7 +348,7 @@
             mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
                     mHandler);
             mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
-            mWakeLock.acquire();
+            mWakeLock.acquire(TAG);
             mRegistered = true;
         }
 
@@ -383,7 +383,7 @@
             }
             onProximityResult(result);
             if (wasRegistered) {
-                mWakeLock.release();
+                mWakeLock.release(TAG);
             }
             mFinished = true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 85d975f..b03b872 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -419,17 +419,16 @@
         return KeyguardUpdateMonitor.getInstance(getContext());
     }
 
+    /**
+     * Called whenever new media metadata is available.
+     * @param metadata New metadata.
+     */
     @Override
     public void onMetadataChanged(MediaMetadata metadata) {
-        final boolean notify;
         synchronized (this) {
-            boolean neededMedia = needsMediaLocked();
             mMediaMetaData = metadata;
-            notify = neededMedia != needsMediaLocked();
         }
-        if (notify) {
-            notifyChange();
-        }
+        notifyChange();
     }
 
     protected void notifyChange() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 164f582..a9fe3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -130,7 +130,7 @@
                 mTextView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
         mDisclosure = indicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure);
         mLockIcon = lockIcon;
-        mWakeLock = new SettableWakeLock(wakeLock);
+        mWakeLock = new SettableWakeLock(wakeLock, TAG);
 
         Resources res = context.getResources();
         mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
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 ee1e3c0..7bbd3b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -340,7 +340,7 @@
         if (!mWakeLockHeld) {
             if (mWakeLock != null) {
                 mWakeLockHeld = true;
-                mWakeLock.acquire();
+                mWakeLock.acquire(TAG);
             } else {
                 Log.w(TAG, "Cannot hold wake lock, it has not been set yet");
             }
@@ -654,7 +654,7 @@
 
     private void onFinished(Callback callback) {
         if (mWakeLockHeld) {
-            mWakeLock.release();
+            mWakeLock.release(TAG);
             mWakeLockHeld = false;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index b835909..7991e38 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,30 +23,34 @@
  */
 public class DelayedWakeLock implements WakeLock {
 
+    private static final String TO_STRING_PREFIX = "[DelayedWakeLock] ";
     private static final long RELEASE_DELAY_MS = 100;
 
     private final Handler mHandler;
     private final WakeLock mInner;
-    private final Runnable mRelease;
 
     public DelayedWakeLock(Handler h, WakeLock inner) {
         mHandler = h;
         mInner = inner;
-        mRelease = mInner::release;
     }
 
     @Override
-    public void acquire() {
-        mInner.acquire();
+    public void acquire(String why) {
+        mInner.acquire(why);
     }
 
     @Override
-    public void release() {
-        mHandler.postDelayed(mRelease, RELEASE_DELAY_MS);
+    public void release(String why) {
+        mHandler.postDelayed(() -> mInner.release(why), RELEASE_DELAY_MS);
     }
 
     @Override
     public Runnable wrap(Runnable r) {
         return WakeLock.wrapImpl(this, r);
     }
+
+    @Override
+    public String toString() {
+        return TO_STRING_PREFIX + mInner;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
index a54b0e1..283be86 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListener.java
@@ -26,6 +26,7 @@
 
 public class KeepAwakeAnimationListener extends AnimatorListenerAdapter
         implements Animation.AnimationListener {
+    private static final String TAG = "KeepAwakeAnimListener";
     @VisibleForTesting
     static WakeLock sWakeLock;
 
@@ -63,11 +64,11 @@
 
     private void onStart() {
         Assert.isMainThread();
-        sWakeLock.acquire();
+        sWakeLock.acquire(TAG);
     }
 
     private void onEnd() {
         Assert.isMainThread();
-        sWakeLock.release();
+        sWakeLock.release(TAG);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index 13729df..a797287 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -21,13 +21,15 @@
 public class SettableWakeLock {
 
     private final WakeLock mInner;
+    private final String mWhy;
 
     private boolean mAcquired;
 
-    public SettableWakeLock(WakeLock inner) {
+    public SettableWakeLock(WakeLock inner, String why) {
         Preconditions.checkNotNull(inner, "inner wakelock required");
 
         mInner = inner;
+        mWhy = why;
     }
 
     public synchronized boolean isAcquired() {
@@ -37,9 +39,9 @@
     public synchronized void setAcquired(boolean acquired) {
         if (mAcquired != acquired) {
             if (acquired) {
-                mInner.acquire();
+                mInner.acquire(mWhy);
             } else {
-                mInner.release();
+                mInner.release(mWhy);
             }
             mAcquired = acquired;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index b0f1b54..bebc20b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -18,17 +18,29 @@
 
 import android.content.Context;
 import android.os.PowerManager;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 
+import java.util.HashMap;
+
 /** WakeLock wrapper for testability */
 public interface WakeLock {
 
-    /** @see android.os.PowerManager.WakeLock#acquire() */
-    void acquire();
+    static final String TAG = "WakeLock";
+    static final String REASON_WRAP = "wrap";
 
-    /** @see android.os.PowerManager.WakeLock#release() */
-    void release();
+    /**
+     * @param why A tag that will be saved for sysui dumps.
+     * @see android.os.PowerManager.WakeLock#acquire()
+     **/
+    void acquire(String why);
+
+    /**
+     * @param why Same tag used in {@link #acquire(String)}
+     * @see android.os.PowerManager.WakeLock#release()
+     **/
+    void release(String why);
 
     /** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
     Runnable wrap(Runnable r);
@@ -44,25 +56,38 @@
     }
 
     static Runnable wrapImpl(WakeLock w, Runnable r) {
-        w.acquire();
+        w.acquire(REASON_WRAP);
         return () -> {
             try {
                 r.run();
             } finally {
-                w.release();
+                w.release(REASON_WRAP);
             }
         };
     }
 
     static WakeLock wrap(final PowerManager.WakeLock inner) {
         return new WakeLock() {
+            private final HashMap<String, Integer> mActiveClients = new HashMap<>();
+
             /** @see PowerManager.WakeLock#acquire() */
-            public void acquire() {
+            public void acquire(String why) {
+                mActiveClients.putIfAbsent(why, 0);
+                mActiveClients.put(why, mActiveClients.get(why) + 1);
                 inner.acquire();
             }
 
             /** @see PowerManager.WakeLock#release() */
-            public void release() {
+            public void release(String why) {
+                Integer count = mActiveClients.get(why);
+                if (count == null) {
+                    Log.wtf(TAG, "Releasing WakeLock with invalid reason: " + why,
+                            new Throwable());
+                } else if (count == 1) {
+                    mActiveClients.remove(why);
+                } else {
+                    mActiveClients.put(why, count - 1);
+                }
                 inner.release();
             }
 
@@ -70,6 +95,11 @@
             public Runnable wrap(Runnable runnable) {
                 return wrapImpl(this, runnable);
             }
+
+            @Override
+            public String toString() {
+                return "active clients= " + mActiveClients.toString();
+            }
         };
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 01d7b8b..e1717be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -166,25 +166,22 @@
 
     @Test
     public void onMetadataChanged_updatesSlice() {
-        mProvider.onMetadataChanged(mock(MediaMetadata.class));
         mProvider.onDozingChanged(true);
+        reset(mContentResolver);
+        mProvider.onMetadataChanged(mock(MediaMetadata.class));
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
 
         // Hides after waking up
         reset(mContentResolver);
         mProvider.onDozingChanged(false);
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
-
-        // And won't update slice if device is awake
-        reset(mContentResolver);
-        mProvider.onMetadataChanged(mock(MediaMetadata.class));
-        verify(mContentResolver, never()).notifyChange(eq(mProvider.getUri()), eq(null));
     }
 
     @Test
     public void onDozingChanged_updatesSliceIfMedia() {
-        // Show media when dozing
         mProvider.onMetadataChanged(mock(MediaMetadata.class));
+        reset(mContentResolver);
+        // Show media when dozing
         mProvider.onDozingChanged(true);
         verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
 
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 c20d37f..e4da859 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
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -441,10 +442,10 @@
     @Test
     public void testHoldsWakeLock_whenAOD() {
         mScrimController.transitionTo(ScrimState.AOD);
-        verify(mWakeLock).acquire();
-        verify(mWakeLock, never()).release();
+        verify(mWakeLock).acquire(anyString());
+        verify(mWakeLock, never()).release(anyString());
         mScrimController.finishAnimationsImmediately();
-        verify(mWakeLock).release();
+        verify(mWakeLock).release(anyString());
     }
 
     @Test
@@ -471,10 +472,10 @@
         reset(mWakeLock);
 
         mScrimController.onHideWallpaperTimeout();
-        verify(mWakeLock).acquire();
-        verify(mWakeLock, never()).release();
+        verify(mWakeLock).acquire(anyString());
+        verify(mWakeLock, never()).release(anyString());
         mScrimController.finishAnimationsImmediately();
-        verify(mWakeLock).release();
+        verify(mWakeLock).release(anyString());
     }
 
     @Test
@@ -486,10 +487,10 @@
         reset(mWakeLock);
 
         mScrimController.onHideWallpaperTimeout();
-        verify(mWakeLock).acquire();
-        verify(mWakeLock, never()).release();
+        verify(mWakeLock).acquire(anyString());
+        verify(mWakeLock, never()).release(anyString());
         mScrimController.finishAnimationsImmediately();
-        verify(mWakeLock).release();
+        verify(mWakeLock).release(anyString());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
index ab9b0c9..0792a05 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.util.wakelock;
 
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -52,11 +53,11 @@
     @Test
     public void onAnimationStart_holdsWakeLock() {
         mKeepAwakeAnimationListener.onAnimationStart((Animator) null);
-        verify(mWakeLock).acquire();
-        verify(mWakeLock, never()).release();
+        verify(mWakeLock).acquire(anyString());
+        verify(mWakeLock, never()).release(anyString());
 
         mKeepAwakeAnimationListener.onAnimationEnd((Animator) null);
-        verify(mWakeLock).release();
+        verify(mWakeLock).release(anyString());
     }
 
     @Test(expected = IllegalStateException.class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
index 39316ed..f739fe6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/SettableWakeLockTest.java
@@ -40,7 +40,7 @@
     @Before
     public void setup() {
         mFake = new WakeLockFake();
-        mSettable = new SettableWakeLock(mFake);
+        mSettable = new SettableWakeLock(mFake, "Fake");
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
index 4cefb99..ef20df2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockFake.java
@@ -23,24 +23,24 @@
     private int mAcquired = 0;
 
     @Override
-    public void acquire() {
+    public void acquire(String why) {
         mAcquired++;
     }
 
     @Override
-    public void release() {
+    public void release(String why) {
         Preconditions.checkState(mAcquired > 0);
         mAcquired--;
     }
 
     @Override
     public Runnable wrap(Runnable runnable) {
-        acquire();
+        acquire(WakeLockFake.class.getSimpleName());
         return () -> {
             try {
                 runnable.run();
             } finally {
-                release();
+                release(WakeLockFake.class.getSimpleName());
             }
         };
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
index d925364..4425def 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
@@ -19,9 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.content.Context;
 import android.os.PowerManager;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -36,6 +34,7 @@
 @RunWith(AndroidJUnit4.class)
 public class WakeLockTest extends SysuiTestCase {
 
+    private static final String WHY = "test";
     WakeLock mWakeLock;
     PowerManager.WakeLock mInner;
 
@@ -58,22 +57,22 @@
 
     @Test
     public void wakeLock_acquire() {
-        mWakeLock.acquire();
+        mWakeLock.acquire(WHY);
         assertTrue(mInner.isHeld());
     }
 
     @Test
     public void wakeLock_release() {
-        mWakeLock.acquire();
-        mWakeLock.release();
+        mWakeLock.acquire(WHY);
+        mWakeLock.release(WHY);
         assertFalse(mInner.isHeld());
     }
 
     @Test
     public void wakeLock_refCounted() {
-        mWakeLock.acquire();
-        mWakeLock.acquire();
-        mWakeLock.release();
+        mWakeLock.acquire(WHY);
+        mWakeLock.acquire(WHY);
+        mWakeLock.release(WHY);
         assertTrue(mInner.isHeld());
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 4a3f126..e0fb337 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -1026,6 +1026,29 @@
         }
 
         @Override
+        public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
+                @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
+                throws RemoteException {
+            final int userId = UserHandle.getCallingUserId();
+
+            boolean ok;
+            synchronized (mLock) {
+                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+                if (service != null) {
+                    ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
+                            getCallingUid());
+                } else {
+                    if (sVerbose) {
+                        Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
+                    }
+                    ok = false;
+                }
+            }
+            send(receiver,
+                    ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
+        }
+
+        @Override
         public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
                 throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 1bce11ee..15dce4a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -40,6 +40,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -58,6 +59,7 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.LocalLog;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -165,6 +167,16 @@
     @Nullable
     private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
 
+    @GuardedBy("mLock")
+    @Nullable
+    private ServiceInfo mRemoteAugmentedAutofillServiceInfo;
+
+    /**
+     * List of packages that are whitelisted to be trigger augmented autofill.
+     */
+    @GuardedBy("mLock")
+    private final ArraySet<String> mWhitelistedAugmentAutofillPackages = new ArraySet<>();
+
     AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
             LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
             AutofillCompatState autofillCompatState,
@@ -844,10 +856,11 @@
     }
 
     @GuardedBy("mLock")
-    private boolean isCalledByServiceLocked(String methodName, int callingUid) {
-        if (getServiceUidLocked() != callingUid) {
+    private boolean isCalledByServiceLocked(@NonNull String methodName, int callingUid) {
+        final int serviceUid = getServiceUidLocked();
+        if (serviceUid != callingUid) {
             Slog.w(TAG, methodName + "() called by UID " + callingUid
-                    + ", but service UID is " + getServiceUidLocked());
+                    + ", but service UID is " + serviceUid);
             return false;
         }
         return true;
@@ -886,6 +899,19 @@
             pw.print(prefix); pw.println("RemoteAugmentedAutofillService: ");
             mRemoteAugmentedAutofillService.dump(prefix2, pw);
         }
+        if (mRemoteAugmentedAutofillServiceInfo != null) {
+            pw.print(prefix); pw.print("RemoteAugmentedAutofillServiceInfo: ");
+            pw.println(mRemoteAugmentedAutofillServiceInfo);
+        }
+
+        final int whitelistSize = mWhitelistedAugmentAutofillPackages.size();
+        pw.print(prefix); pw.print("Packages whitelisted for augmented autofill: ");
+        pw.println(whitelistSize);
+        for (int i = 0; i < whitelistSize; i++) {
+            final String whitelistedPkg = mWhitelistedAugmentAutofillPackages.valueAt(i);
+            pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
+        }
+
         pw.print(prefix); pw.print("Field classification enabled: ");
             pw.println(isFieldClassificationEnabledLocked());
         pw.print(prefix); pw.print("Compat pkgs: ");
@@ -1037,9 +1063,13 @@
                 }
                 return null;
             }
-            final ComponentName componentName = RemoteAugmentedAutofillService.getComponentName(
-                    serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
-            if (componentName == null) return null;
+            final Pair<ServiceInfo, ComponentName> pair = RemoteAugmentedAutofillService
+                    .getComponentName(
+                            serviceName, mUserId, mAugmentedAutofillResolver.isTemporary(mUserId));
+            if (pair == null) return null;
+
+            mRemoteAugmentedAutofillServiceInfo = pair.first;
+            final ComponentName componentName = pair.second;
             if (sVerbose) {
                 Slog.v(TAG, "getRemoteAugmentedAutofillServiceLocked(): " + componentName);
             }
@@ -1067,13 +1097,92 @@
     private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) {
         if (serviceName == null) {
             if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
-            if (mRemoteAugmentedAutofillService != null) {
-                mRemoteAugmentedAutofillService.destroy();
-                mRemoteAugmentedAutofillService = null;
+            synchronized (mLock) {
+                if (mRemoteAugmentedAutofillService != null) {
+                    mRemoteAugmentedAutofillService.destroy();
+                    mRemoteAugmentedAutofillService = null;
+                }
             }
         }
     }
 
+    /**
+     * Sets which packages and activities can trigger augmented autofill.
+     *
+     * @return whether caller UID is the augmented autofill service for the user
+     */
+    boolean setAugmentedAutofillWhitelistLocked(List<String> packages,
+            List<ComponentName> activities, int callingUid) {
+
+        if (!isCalledByAugmentedAutofillServiceLocked("setAugmentedAutofillWhitelistLocked",
+                callingUid)) {
+            return false;
+        }
+        if (mMaster.verbose) {
+            Slog.v(TAG, "setAugmentedAutofillWhitelistLocked(packages=" + packages + ", activities="
+                    + activities + ")");
+        }
+        whitelistForAugmentedAutofillPackages(packages);
+
+        // TODO(b/123100824): whitelist activities as well
+        // TODO(b/122858578): log metrics
+        return true;
+    }
+
+    @GuardedBy("mLock")
+    private boolean isCalledByAugmentedAutofillServiceLocked(@NonNull String methodName,
+            int callingUid) {
+        // Lazy load service first
+        final RemoteAugmentedAutofillService service = getRemoteAugmentedAutofillServiceLocked();
+        if (service == null) {
+            Slog.w(TAG, methodName + "() called by UID " + callingUid
+                    + ", but there is no augmented autofill service defined for user "
+                    + getUserId());
+            return false;
+        }
+
+        if (getAugmentedAutofillServiceUidLocked() != callingUid) {
+            Slog.w(TAG, methodName + "() called by UID " + callingUid
+                    + ", but service UID is " + getAugmentedAutofillServiceUidLocked()
+                    + " for user " + getUserId());
+            return false;
+        }
+        return true;
+    }
+
+    @GuardedBy("mLock")
+    private int getAugmentedAutofillServiceUidLocked() {
+        if (mRemoteAugmentedAutofillServiceInfo == null) {
+            if (mMaster.verbose) {
+                Slog.v(TAG, "getAugmentedAutofillServiceUid(): "
+                        + "no mRemoteAugmentedAutofillServiceInfo");
+            }
+            return Process.INVALID_UID;
+        }
+        return mRemoteAugmentedAutofillServiceInfo.applicationInfo.uid;
+    }
+
+    @GuardedBy("mLock")
+    boolean isWhitelistedForAugmentedAutofillLocked(@NonNull ComponentName componentName) {
+        // TODO(b/122595322): need to check whitelisted activities as well.
+        final String packageName = componentName.getPackageName();
+        return mWhitelistedAugmentAutofillPackages.contains(packageName);
+    }
+
+    private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
+        // TODO(b/123100824): add CTS test for when it's null
+        synchronized (mLock) {
+            if (packages == null) {
+                if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted augmented packages");
+                mWhitelistedAugmentAutofillPackages.clear();
+            } else {
+                if (mMaster.verbose) Slog.v(TAG, "whitelisting augmented packages: " + packages);
+                mWhitelistedAugmentAutofillPackages.addAll(packages);
+            }
+            mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
+        }
+    }
+
     private void sendStateToClients(boolean resetClient) {
         final RemoteCallbackList<IAutoFillManagerClient> clients;
         final int userClientCount;
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 61f63d3..88228fb 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -32,6 +32,7 @@
 import android.service.autofill.augmented.IAugmentedAutofillService;
 import android.service.autofill.augmented.IFillCallback;
 import android.text.format.DateUtils;
+import android.util.Pair;
 import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
@@ -54,10 +55,13 @@
             boolean bindInstantServiceAllowed, boolean verbose) {
         super(context, AugmentedAutofillService.SERVICE_INTERFACE, serviceName, userId, callbacks,
                 bindInstantServiceAllowed, verbose);
+
+        // Bind right away.
+        scheduleBind();
     }
 
     @Nullable
-    public static ComponentName getComponentName(@NonNull String componentName,
+    static Pair<ServiceInfo, ComponentName> getComponentName(@NonNull String componentName,
             @UserIdInt int userId, boolean isTemporary) {
         int flags = PackageManager.GET_META_DATA;
         if (!isTemporary) {
@@ -78,7 +82,23 @@
             Slog.e(TAG, "Error getting service info for '" + componentName + "': " + e);
             return null;
         }
-        return serviceComponent;
+        return new Pair<>(serviceInfo, serviceComponent);
+    }
+
+    @Override // from RemoteService
+    protected void handleOnConnectedStateChanged(boolean state) {
+        if (state && getTimeoutIdleBindMillis() != PERMANENT_BOUND_TIMEOUT_MS) {
+            scheduleUnbind();
+        }
+        try {
+            if (state) {
+                mService.onConnected();
+            } else {
+                mService.onDisconnected();
+            }
+        } catch (Exception e) {
+            Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e);
+        }
     }
 
     @Override // from AbstractRemoteService
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 04fc258..848f249 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2613,13 +2613,25 @@
                     + " when server returned null for session " + this.id);
         }
 
+        final boolean isWhitelisted = mService
+                .isWhitelistedForAugmentedAutofillLocked(mComponentName);
+
         final String historyItem =
                 "aug:id=" + id + " u=" + uid + " m=" + mode
                 + " a=" + ComponentName.flattenToShortString(mComponentName)
                 + " f=" + mCurrentViewId
-                + " s=" + remoteService.getComponentName();
+                + " s=" + remoteService.getComponentName()
+                + " w=" + isWhitelisted;
         mService.getMaster().logRequestLocked(historyItem);
 
+        if (!isWhitelisted) {
+            if (sVerbose) {
+                Slog.v(TAG, mComponentName.toShortString() + " is not whitelisted for "
+                        + "augmented autofill");
+            }
+            return null;
+        }
+
         final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
 
         // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bfe1f6a..96cd79b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5615,7 +5615,7 @@
     int checkCallingPermission(String permission) {
         return checkPermission(permission,
                 Binder.getCallingPid(),
-                UserHandle.getAppId(Binder.getCallingUid()));
+                Binder.getCallingUid());
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b1c186e..9ff2f44 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15835,6 +15835,12 @@
 
             if (reconciledPkg.prepareResult.replace) {
                 PackageParser.Package oldPackage = mPackages.get(packageName);
+
+                // Set the update and install times
+                PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
+                setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
+                        System.currentTimeMillis());
+
                 if (reconciledPkg.prepareResult.system) {
                     // Remove existing system package
                     removePackageLI(oldPackage, true);
@@ -15850,11 +15856,6 @@
                         res.removedInfo.args = null;
                     }
 
-                    // Set the update and install times
-                    PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras;
-                    setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime,
-                            System.currentTimeMillis());
-
                     // Update the package dynamic state if succeeded
                     // Now that the install succeeded make sure we remove data
                     // directories for any child package the update removed.
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index dacc6cd..6369179 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -642,10 +642,16 @@
         // Location
         if (locationPackageNames != null) {
             for (String packageName : locationPackageNames) {
+                // STOPSHIP: remove this force-granting of legacy storage
+                // permissions once b/124466734 is resolved
+                final Set<String> storageWorkaround = new ArraySet<>();
+                storageWorkaround.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+                storageWorkaround.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
                 grantPermissionsToSystemPackage(packageName, userId,
                         CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
                         PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
-                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
+                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, storageWorkaround);
                 grantSystemFixedPermissionsToSystemPackage(packageName, userId,
                         LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 538813e..9ea819e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -938,7 +938,7 @@
             return false;
         }
         // don't abort if the callingUid is in the foreground or is a persistent system process
-        final int callingUidProcState = mService.getUidStateLocked(callingUid);
+        final int callingUidProcState = mService.getUidState(callingUid);
         final boolean callingUidHasAnyVisibleWindow =
                 mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
         final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
@@ -951,7 +951,7 @@
         // take realCallingUid into consideration
         final int realCallingUidProcState = (callingUid == realCallingUid)
                 ? callingUidProcState
-                : mService.getUidStateLocked(realCallingUid);
+                : mService.getUidState(realCallingUid);
         final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
                 ? callingUidHasAnyVisibleWindow
                 : mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(realCallingUid);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 9b35e85..f24d680 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -26,7 +26,6 @@
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.Manifest.permission.STOP_APP_SWITCHES;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
@@ -272,6 +271,10 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.lang.ref.WeakReference;
 import java.text.DateFormat;
 import java.util.ArrayList;
@@ -363,7 +366,7 @@
     private UserManagerService mUserManager;
     private AppOpsService mAppOpsService;
     /** All active uids in the system. */
-    private final SparseArray<Integer> mActiveUids = new SparseArray<>();
+    private final MirrorActiveUids mActiveUids = new MirrorActiveUids();
     private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
     /** All processes currently running that might have a window organized by name. */
     final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
@@ -647,6 +650,17 @@
         }
     }
 
+    /** Indicates that the method may be invoked frequently or is sensitive to performance. */
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.SOURCE)
+    @interface HotPath {
+        int NONE = 0;
+        int OOM_ADJUSTMENT = 1;
+        int LRU_UPDATE = 2;
+        int PROCESS_CHANGE = 3;
+        int caller() default NONE;
+    }
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public ActivityTaskManagerService(Context context) {
         mContext = context;
@@ -5720,12 +5734,12 @@
         return null;
     }
 
-    int getUidStateLocked(int uid) {
-        return mActiveUids.get(uid, PROCESS_STATE_NONEXISTENT);
+    int getUidState(int uid) {
+        return mActiveUids.getUidState(uid);
     }
 
     boolean isUidForeground(int uid) {
-        return (getUidStateLocked(uid) == ActivityManager.PROCESS_STATE_TOP)
+        return (getUidState(uid) == ActivityManager.PROCESS_STATE_TOP)
                 || mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
     }
 
@@ -6118,23 +6132,26 @@
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void onProcessAdded(WindowProcessController proc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mProcessNames.put(proc.mName, proc.mUid, proc);
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void onProcessRemoved(String name, int uid) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mProcessNames.remove(name, uid);
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void onCleanUpApplicationRecord(WindowProcessController proc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 if (proc == mHomeProcess) {
                     mHomeProcess = null;
                 }
@@ -6144,23 +6161,26 @@
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public int getTopProcessState() {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 return mTopProcessState;
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public boolean isHeavyWeightProcess(WindowProcessController proc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 return proc == mHeavyWeightProcess;
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void clearHeavyWeightProcessIfEquals(WindowProcessController proc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 ActivityTaskManagerService.this.clearHeavyWeightProcessIfEquals(proc);
             }
         }
@@ -6176,9 +6196,10 @@
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public boolean isSleeping() {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 return isSleepingLocked();
             }
         }
@@ -6422,9 +6443,10 @@
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public boolean isFactoryTestProcess(WindowProcessController wpc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 if (mFactoryTest == FACTORY_TEST_OFF) {
                     return false;
                 }
@@ -6477,10 +6499,11 @@
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void handleAppDied(WindowProcessController wpc, boolean restarting,
                 Runnable finishInstrumentationCallback) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 // Remove this application's activities from active lists.
                 boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc);
 
@@ -6579,16 +6602,18 @@
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public void preBindApplication(WindowProcessController wpc) {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(wpc.mInfo);
             }
         }
 
+        @HotPath(caller = HotPath.PROCESS_CHANGE)
         @Override
         public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
-            synchronized (mGlobalLock) {
+            synchronized (mGlobalLockWithoutBoost) {
                 return mRootActivityContainer.attachApplication(wpc);
             }
         }
@@ -6916,6 +6941,7 @@
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public WindowProcessController getTopApp() {
             synchronized (mGlobalLockWithoutBoost) {
@@ -6924,6 +6950,7 @@
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public void rankTaskLayersIfNeeded() {
             synchronized (mGlobalLockWithoutBoost) {
@@ -6968,34 +6995,28 @@
             }
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public void onUidActive(int uid, int procState) {
-            synchronized (mGlobalLockWithoutBoost) {
-                mActiveUids.put(uid, procState);
-            }
+            mActiveUids.onUidActive(uid, procState);
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public void onUidInactive(int uid) {
-            synchronized (mGlobalLockWithoutBoost) {
-                mActiveUids.remove(uid);
-            }
+            mActiveUids.onUidInactive(uid);
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public void onActiveUidsCleared() {
-            synchronized (mGlobalLockWithoutBoost) {
-                mActiveUids.clear();
-            }
+            mActiveUids.onActiveUidsCleared();
         }
 
+        @HotPath(caller = HotPath.OOM_ADJUSTMENT)
         @Override
         public void onUidProcStateChanged(int uid, int procState) {
-            synchronized (mGlobalLockWithoutBoost) {
-                if (mActiveUids.get(uid) != null) {
-                    mActiveUids.put(uid, procState);
-                }
-            }
+            mActiveUids.onUidProcStateChanged(uid, procState);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e65973a..a19721f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -37,7 +37,6 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.GONE;
-import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
@@ -174,7 +173,6 @@
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
 import android.view.View;
-import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
@@ -3270,9 +3268,6 @@
     }
 
     private void updateImeParent() {
-        if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE) {
-            return;
-        }
         final SurfaceControl newParent = computeImeParent();
         if (newParent != null) {
             mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java
new file mode 100644
index 0000000..0047942
--- /dev/null
+++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+
+import android.util.SparseIntArray;
+
+/**
+ * This is a partial mirror of {@link @com.android.server.am.ActiveUids}. It is already thread
+ * safe so the heavy service lock is not needed when updating state from activity manager (oom
+ * adjustment) or getting state from window manager (background start check).
+ */
+class MirrorActiveUids {
+    private SparseIntArray mUidStates = new SparseIntArray();
+
+    synchronized void onUidActive(int uid, int procState) {
+        mUidStates.put(uid, procState);
+    }
+
+    synchronized void onUidInactive(int uid) {
+        mUidStates.delete(uid);
+    }
+
+    synchronized void onActiveUidsCleared() {
+        mUidStates.clear();
+    }
+
+    synchronized void onUidProcStateChanged(int uid, int procState) {
+        final int index = mUidStates.indexOfKey(uid);
+        if (index >= 0) {
+            mUidStates.setValueAt(index, procState);
+        }
+    }
+
+    synchronized int getUidState(int uid) {
+        return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT);
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b915199..fc95789 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -71,6 +71,7 @@
 import android.view.DisplayInfo;
 import android.view.SurfaceControl;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
 import com.android.internal.policy.DockedDividerUtils;
@@ -787,6 +788,14 @@
         return 0;
     }
 
+    @Override
+    void getRelativeDisplayedPosition(Point outPos) {
+        super.getRelativeDisplayedPosition(outPos);
+        final int outset = getStackOutset();
+        outPos.x -= outset;
+        outPos.y -= outset;
+    }
+
     private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
         if (mSurfaceControl == null) {
             return;
@@ -807,6 +816,11 @@
         mLastSurfaceSize.set(width, height);
     }
 
+    @VisibleForTesting
+    Point getLastSurfaceSize() {
+        return mLastSurfaceSize;
+    }
+
     @Override
     void onDisplayChanged(DisplayContent dc) {
         if (mDisplayContent != null && mDisplayContent != dc) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 465f413..dceed28 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -57,6 +57,7 @@
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.Watchdog;
+import com.android.server.wm.ActivityTaskManagerService.HotPath;
 
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -408,12 +409,14 @@
         return null;
     }
 
+    @HotPath(caller = HotPath.PROCESS_CHANGE)
     public void addPackage(String packageName) {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             mPkgList.add(packageName);
         }
     }
 
+    @HotPath(caller = HotPath.PROCESS_CHANGE)
     public void clearPackageList() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             mPkgList.clear();
@@ -441,12 +444,14 @@
         mActivities.clear();
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public boolean hasActivities() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mActivities.isEmpty();
         }
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public boolean hasVisibleActivities() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             for (int i = mActivities.size() - 1; i >= 0; --i) {
@@ -459,6 +464,7 @@
         return false;
     }
 
+    @HotPath(caller = HotPath.LRU_UPDATE)
     public boolean hasActivitiesOrRecentTasks() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mActivities.isEmpty() || !mRecentTasks.isEmpty();
@@ -670,6 +676,7 @@
         void onOtherActivity();
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public int computeOomAdjFromActivities(int minTaskLayer, ComputeOomAdjCallback callback) {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             final int activitiesSize = mActivities.size();
@@ -903,6 +910,7 @@
         mRecentTasks.remove(task);
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public boolean hasRecentTasks() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             return !mRecentTasks.isEmpty();
@@ -966,18 +974,21 @@
         return false;
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public void onTopProcChanged() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             mAtm.mVrController.onTopProcChangedLocked(this);
         }
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public boolean isHomeProcess() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             return this == mAtm.mHomeProcess;
         }
     }
 
+    @HotPath(caller = HotPath.OOM_ADJUSTMENT)
     public boolean isPreviousProcess() {
         synchronized (mAtm.mGlobalLockWithoutBoost) {
             return this == mAtm.mPreviousProcess;
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index 8d9b3cf..fe4825c 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -23,12 +23,14 @@
 import static org.testng.Assert.assertEquals;
 
 import android.app.usage.EventList;
+import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.AtomicFile;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -38,6 +40,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
@@ -448,4 +451,45 @@
         runBackupRestoreTest(0);
         runBackupRestoreTest(99999);
     }
+
+    /**
+     * Test the pruning in indexFilesLocked() that only allow up to 100 daily files, 50 weekly files
+     * , 12 monthly files, 10 yearly files.
+     */
+    @Test
+    public void testMaxFiles() throws IOException {
+        final File[] intervalDirs = new File[]{
+            new File(mTestDir, "daily"),
+            new File(mTestDir, "weekly"),
+            new File(mTestDir, "monthly"),
+            new File(mTestDir, "yearly"),
+        };
+        // Create 10 extra files under each interval dir.
+        final int extra = 10;
+        final int length = intervalDirs.length;
+        for (int i = 0; i < length; i++) {
+            final int numFiles = UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i] + extra;
+            for (int f = 0; f < numFiles; f++) {
+                final AtomicFile file = new AtomicFile(new File(intervalDirs[i], Long.toString(f)));
+                FileOutputStream fos = file.startWrite();
+                fos.write(1);
+                file.finishWrite(fos);
+            }
+        }
+        // indexFilesLocked() list files under each interval dir, if number of files are more than
+        // the max allowed files for each interval type, it deletes the lowest numbered files.
+        mUsageStatsDatabase.forceIndexFiles();
+        final int len = mUsageStatsDatabase.mSortedStatFiles.length;
+        for (int i = 0; i < len; i++) {
+            final TimeSparseArray<AtomicFile> files =  mUsageStatsDatabase.mSortedStatFiles[i];
+            // The stats file for each interval type equals to max allowed.
+            assertEquals(UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i],
+                    files.size());
+            // The highest numbered file,
+            assertEquals(UsageStatsDatabase.MAX_FILES_PER_INTERVAL_TYPE[i] + extra - 1,
+                    files.keyAt(files.size() - 1));
+            // The lowest numbered file:
+            assertEquals(extra, files.keyAt(0));
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 392b010..606ab31 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -661,8 +661,8 @@
         doReturn(realCallingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                 .isAnyNonToastWindowVisibleForUid(realCallingUid);
         // process importance
-        doReturn(callingUidProcState).when(mService).getUidStateLocked(callingUid);
-        doReturn(realCallingUidProcState).when(mService).getUidStateLocked(realCallingUid);
+        doReturn(callingUidProcState).when(mService).getUidState(callingUid);
+        doReturn(realCallingUidProcState).when(mService).getUidState(realCallingUid);
         // foreground activities
         final IApplicationThread caller = mock(IApplicationThread.class);
         final ApplicationInfo ai = new ApplicationInfo();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 2554237..b1f942e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -19,6 +19,9 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
@@ -168,4 +171,22 @@
         assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
         assertTrue(task1.mOnDisplayChangedCalled);
     }
+
+    @Test
+    public void testStackOutset() {
+        final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
+        spyOn(stack);
+
+        final int stackOutset = 10;
+        doReturn(stackOutset).when(stack).getStackOutset();
+
+        final Rect stackBounds = new Rect(200, 200, 800, 1000);
+        // Update surface position and size by the given bounds.
+        stack.setBounds(stackBounds);
+
+        assertEquals(stackBounds.width() + 2 * stackOutset, stack.getLastSurfaceSize().x);
+        assertEquals(stackBounds.height() + 2 * stackOutset, stack.getLastSurfaceSize().y);
+        assertEquals(stackBounds.left - stackOutset, stack.getLastSurfacePosition().x);
+        assertEquals(stackBounds.top - stackOutset, stack.getLastSurfacePosition().y);
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 0e15947..dff6809 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -43,8 +43,8 @@
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.FilenameFilter;
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
@@ -84,6 +84,9 @@
     @VisibleForTesting
     public static final int BACKUP_VERSION = 4;
 
+    @VisibleForTesting
+    static final int[] MAX_FILES_PER_INTERVAL_TYPE = new int[]{100, 50, 12, 10};
+
     // Key under which the payload blob is stored
     // same as UsageStatsBackupHelper.KEY_USAGE_STATS
     static final String KEY_USAGE_STATS = "usage_stats";
@@ -104,7 +107,8 @@
 
     private final Object mLock = new Object();
     private final File[] mIntervalDirs;
-    private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
+    @VisibleForTesting
+    final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
     private final UnixCalendar mCal;
     private final File mVersionFile;
     private final File mBackupsDir;
@@ -126,10 +130,10 @@
     @VisibleForTesting
     public UsageStatsDatabase(File dir, int version) {
         mIntervalDirs = new File[]{
-                new File(dir, "daily"),
-                new File(dir, "weekly"),
-                new File(dir, "monthly"),
-                new File(dir, "yearly"),
+            new File(dir, "daily"),
+            new File(dir, "weekly"),
+            new File(dir, "monthly"),
+            new File(dir, "yearly"),
         };
         mCurrentVersion = version;
         mVersionFile = new File(dir, "version");
@@ -248,6 +252,14 @@
         return true;
     }
 
+    /** @hide */
+    @VisibleForTesting
+    void forceIndexFiles() {
+        synchronized (mLock) {
+            indexFilesLocked();
+        }
+    }
+
     private void indexFilesLocked() {
         final FilenameFilter backupFileFilter = new FilenameFilter() {
             @Override
@@ -255,7 +267,6 @@
                 return !name.endsWith(BAK_SUFFIX);
             }
         };
-
         // Index the available usage stat files on disk.
         for (int i = 0; i < mSortedStatFiles.length; i++) {
             if (mSortedStatFiles[i] == null) {
@@ -268,8 +279,9 @@
                 if (DEBUG) {
                     Slog.d(TAG, "Found " + files.length + " stat files for interval " + i);
                 }
-
-                for (File f : files) {
+                final int len = files.length;
+                for (int j = 0; j < len; j++) {
+                    final File f = files[j];
                     final AtomicFile af = new AtomicFile(f);
                     try {
                         mSortedStatFiles[i].put(parseBeginTime(af), af);
@@ -277,6 +289,16 @@
                         Slog.e(TAG, "failed to index file: " + f, e);
                     }
                 }
+
+                // only keep the max allowed number of files for each interval type.
+                final int toDelete = mSortedStatFiles[i].size() - MAX_FILES_PER_INTERVAL_TYPE[i];
+                if (toDelete > 0) {
+                    for (int j = 0; j < toDelete; j++) {
+                        mSortedStatFiles[i].valueAt(0).delete();
+                        mSortedStatFiles[i].removeAt(0);
+                    }
+                    Slog.d(TAG, "Deleted " + toDelete + " stat files for interval " + i);
+                }
             }
         }
     }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 3cb2216..ebd8e36 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -595,8 +595,8 @@
     private void loadActiveStats(final long currentTimeMillis) {
         for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
             final IntervalStats stats = mDatabase.getLatestUsageStats(intervalType);
-            if (stats != null && currentTimeMillis - 500 >= stats.endTime &&
-                    currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
+            if (stats != null
+                    && currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
                 if (DEBUG) {
                     Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
                             sDateFormat.format(stats.beginTime) + "(" + stats.beginTime +
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 2462bee..fecdb08 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2186,7 +2186,10 @@
 
             /**
              * The URI to query or modify {@link android.telephony.ims.Rcs1To1Thread}s via the
-             * content provider
+             * content provider. Can also insert to this URI to create a new 1-to-1 thread. When
+             * performing an insert, ensure that the provided content values contain the other
+             * participant's ID under the key
+             * {@link RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN}
              */
             Uri RCS_1_TO_1_THREAD_URI = Uri.withAppendedPath(CONTENT_AND_AUTHORITY,
                     RCS_1_TO_1_THREAD_URI_PART);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1b7228a..ad98e36 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2481,6 +2481,17 @@
             "opportunistic_network_data_switch_hysteresis_time_long";
 
     /**
+     * Indicates zero or more emergency number prefix(es), because some carrier requires
+     * if users dial an emergency number address with a specific prefix, the combination of the
+     * prefix and the address is also a valid emergency number to dial. For example, an emergency
+     * number prefix is 318, and the emergency number is 911. Both 318911 and 911 can be dialed by
+     * users for emergency call. An empty array of string indicates that current carrier does not
+     * have this requirement.
+     */
+    public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY =
+            "emergency_number_prefix_string_array";
+
+    /**
      * GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
      * @hide
      */
@@ -2989,6 +3000,7 @@
                 new int[] {
                         1 /* Roaming Indicator Off */
                 });
+        sDefaults.putStringArray(KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY, new String[0]);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 6958d22..7655834 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -23,6 +23,7 @@
 import android.text.TextUtils;
 
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * CellIdentity represents the identity of a unique cell. This is the base class for
@@ -83,6 +84,13 @@
             mMncStr = null;
             log("invalid MNC format: " + mnc);
         }
+
+        if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
+            DebugEventReporter.sendEvent(
+                    UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
+                    "CellIdentity Missing Half of PLMN ID");
+        }
+
         mAlphaLong = alphal;
         mAlphaShort = alphas;
     }