Merge "Fix current.txt error"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ff40f75..5c21221 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,6 +5,7 @@
                       packages/PrintRecommendationService/
                       packages/PrintSpooler/
                       packages/PackageInstaller/
+                      packages/SystemUI/
                       services/print/
                       services/usb/
                       telephony/
diff --git a/api/current.txt b/api/current.txt
index be41608..5951433 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -52310,6 +52310,7 @@
     field public static final int ERROR_UNSAFE_RESOURCE = -16; // 0xfffffff0
     field public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; // 0xfffffffd
     field public static final int ERROR_UNSUPPORTED_SCHEME = -10; // 0xfffffff6
+    field public static final int SAFE_BROWSING_THREAT_BILLING = 4; // 0x4
     field public static final int SAFE_BROWSING_THREAT_MALWARE = 1; // 0x1
     field public static final int SAFE_BROWSING_THREAT_PHISHING = 2; // 0x2
     field public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0; // 0x0
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 2f05a52..5818f5d 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -218,6 +218,7 @@
     tests/metrics/metrics_test_helper.cpp \
     tests/statsd_test_util.cpp \
     tests/e2e/WakelockDuration_e2e_test.cpp \
+    tests/e2e/MetricActivation_e2e_test.cpp \
     tests/e2e/MetricConditionLink_e2e_test.cpp \
     tests/e2e/Alarm_e2e_test.cpp \
     tests/e2e/Attribution_e2e_test.cpp \
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 3eb83b4..3e8b9b8 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -219,6 +219,7 @@
 
     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index df08181..f87849e 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -64,8 +64,54 @@
         onMatchedLogEventInternalLocked(
                 matcherIndex, metricKey, conditionKey, condition, event);
     }
+}
 
- }
+bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
+    bool isActive = mEventActivationMap.empty();
+    for (auto& it : mEventActivationMap) {
+        if (it.second.state == ActivationState::kActive &&
+            elapsedTimestampNs > it.second.ttl_ns + it.second.activation_ns) {
+            it.second.state = ActivationState::kNotActive;
+        }
+        if (it.second.state == ActivationState::kActive) {
+            isActive = true;
+        }
+    }
+    return isActive;
+}
+
+void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (!mIsActive) {
+        return;
+    }
+    mIsActive = evaluateActiveStateLocked(elapsedTimestampNs);
+    if (!mIsActive) {
+        flushLocked(elapsedTimestampNs);
+    }
+}
+
+void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    // When a metric producer does not depend on any activation, its mIsActive is true.
+    // Therefor, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
+    // change.
+    if  (mEventActivationMap.empty()) {
+        mIsActive = false;
+    }
+    mEventActivationMap[activationTrackerIndex].ttl_ns = ttl_seconds * NS_PER_SEC;
+}
+
+void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs) {
+    auto it = mEventActivationMap.find(activationTrackerIndex);
+    if (it == mEventActivationMap.end()) {
+        return;
+    }
+    it->second.activation_ns = elapsedTimestampNs;
+    it->second.state = ActivationState::kActive;
+    mIsActive = true;
+}
+
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 6fe4bfb..b21fd50 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -34,6 +34,17 @@
 namespace os {
 namespace statsd {
 
+// If the metric has no activation requirement, it will be active once the metric producer is
+// created.
+// If the metric needs to be activated by atoms, the metric producer will start
+// with kNotActive state, turn to kActive when the activation event arrives, become kNotActive
+// when it reaches the duration limit (timebomb). If the activation event arrives again before
+// or after it expires, the event producer will be re-activated and ttl will be reset.
+enum ActivationState {
+    kNotActive = 0,
+    kActive = 1,
+};
+
 // 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
@@ -54,7 +65,8 @@
           mContainANYPositionInDimensionsInWhat(false),
           mSliceByPositionALL(false),
           mSameConditionDimensionsInTracker(false),
-          mHasLinksToAllConditionDimensionsInTracker(false) {
+          mHasLinksToAllConditionDimensionsInTracker(false),
+          mIsActive(true) {
     }
 
     virtual ~MetricProducer(){};
@@ -93,17 +105,23 @@
     // Consume the parsed stats log entry that already matched the "what" of the metric.
     void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onMatchedLogEventLocked(matcherIndex, event);
+        if (mIsActive) {
+            onMatchedLogEventLocked(matcherIndex, event);
+        }
     }
 
     void onConditionChanged(const bool condition, const int64_t eventTime) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onConditionChangedLocked(condition, eventTime);
+        if (mIsActive) {
+            onConditionChangedLocked(condition, eventTime);
+        }
     }
 
     void onSlicedConditionMayChange(bool overallCondition, const int64_t eventTime) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onSlicedConditionMayChangeLocked(overallCondition, eventTime);
+        if (mIsActive) {
+            onSlicedConditionMayChangeLocked(overallCondition, eventTime);
+        }
     }
 
     bool isConditionSliced() const {
@@ -177,6 +195,15 @@
         return mCurrentBucketNum;
     }
 
+    void activate(int activationTrackerIndex, int64_t elapsedTimestampNs) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        activateLocked(activationTrackerIndex, elapsedTimestampNs);
+    }
+
+    void addActivation(int activationTrackerIndex, int64_t ttl_seconds);
+
+    void flushIfExpire(int64_t elapsedTimestampNs);
+
 protected:
     virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
     virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
@@ -189,6 +216,10 @@
     virtual size_t byteSizeLocked() const = 0;
     virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
 
+    bool evaluateActiveStateLocked(int64_t elapsedTimestampNs);
+
+    void activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs);
+
     /**
      * Flushes the current bucket if the eventTime is after the current bucket's end time. This will
        also flush the current partial bucket in memory.
@@ -198,9 +229,9 @@
     /**
      * Flushes all the data including the current partial bucket.
      */
-    virtual void flushLocked(const int64_t& eventTime) {
-        flushIfNeededLocked(eventTime);
-        flushCurrentBucketLocked(eventTime);
+    virtual void flushLocked(const int64_t& eventTimeNs) {
+        flushIfNeededLocked(eventTimeNs);
+        flushCurrentBucketLocked(eventTimeNs);
     };
 
     /**
@@ -295,6 +326,21 @@
     virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event);
 
     mutable std::mutex mMutex;
+
+    struct Activation {
+        Activation() : ttl_ns(0), activation_ns(0), state(ActivationState::kNotActive)  {}
+
+        int64_t ttl_ns;
+        int64_t activation_ns;
+        ActivationState state;
+    };
+    // When the metric producer has multiple activations, these activations are ORed to determine
+    // whether the metric producer is ready to generate metrics.
+    std::unordered_map<int, Activation> mEventActivationMap;
+
+    bool mIsActive;
+
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 0e5ef4d..f85ba1f 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -73,7 +73,8 @@
             key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
             timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
             mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
-            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, mNoReportMetricIds);
+            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
+            mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
 
     mHashStringsInReport = config.hash_strings_in_metric_report();
 
@@ -298,7 +299,12 @@
     }
 
     int tagId = event.GetTagId();
-    int64_t eventTime = event.GetElapsedTimestampNs();
+    int64_t eventTimeNs = event.GetElapsedTimestampNs();
+
+    for (int metric : mMetricIndexesWithActivation) {
+        mAllMetricProducers[metric]->flushIfExpire(eventTimeNs);
+    }
+
     if (mTagIds.find(tagId) == mTagIds.end()) {
         // not interesting...
         return;
@@ -310,6 +316,14 @@
         matcher->onLogEvent(event, mAllAtomMatchers, matcherCache);
     }
 
+    for (const auto& it : mActivationAtomTrackerToMetricMap) {
+        if (matcherCache[it.first] == MatchingState::kMatched) {
+            for (int metricIndex : it.second) {
+                mAllMetricProducers[metricIndex]->activate(it.first, eventTimeNs);
+            }
+        }
+    }
+
     // A bitmap to see which ConditionTracker needs to be re-evaluated.
     vector<bool> conditionToBeEvaluated(mAllConditionTrackers.size(), false);
 
@@ -347,13 +361,13 @@
                 // Push the new condition to it directly.
                 if (!mAllMetricProducers[metricIndex]->isConditionSliced()) {
                     mAllMetricProducers[metricIndex]->onConditionChanged(conditionCache[i],
-                                                                         eventTime);
+                                                                         eventTimeNs);
                     // metric cares about sliced conditions, and it may have changed. Send
                     // notification, and the metric can query the sliced conditions that are
                     // interesting to it.
                 } else {
                     mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i],
-                                                                                 eventTime);
+                                                                                 eventTimeNs);
                 }
             }
         }
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index e8029a2..649222ff 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -195,6 +195,11 @@
     // maps from ConditionTracker to MetricProducer
     std::unordered_map<int, std::vector<int>> mConditionToMetricMap;
 
+    // maps from life span triggering event to MetricProducers.
+    std::unordered_map<int, std::vector<int>> mActivationAtomTrackerToMetricMap;
+
+    std::vector<int> mMetricIndexesWithActivation;
+
     void initLogSourceWhiteList();
 
     // The metrics that don't need to be uploaded or even reported.
@@ -230,6 +235,7 @@
 
     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 481099a..136ba07 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -685,6 +685,44 @@
     return true;
 }
 
+bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
+                           const int64_t currentTimeNs,
+                           const unordered_map<int64_t, int> &logEventTrackerMap,
+                           const unordered_map<int64_t, int> &metricProducerMap,
+                           vector<sp<MetricProducer>>& allMetricProducers,
+                           unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+                           vector<int>& metricsWithActivation) {
+    for (int i = 0; i < config.metric_activation_size(); ++i) {
+        const MetricActivation& metric_activation = config.metric_activation(i);
+        auto itr = metricProducerMap.find(metric_activation.metric_id());
+        if (itr == metricProducerMap.end()) {
+            ALOGE("Metric id not found in metric activation: %lld",
+                (long long)metric_activation.metric_id());
+            return false;
+        }
+        const int metricTrackerIndex = itr->second;
+        if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
+            ALOGE("Invalid metric tracker index.");
+            return false;
+        }
+        metricsWithActivation.push_back(metricTrackerIndex);
+        for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
+            const EventActivation& activation = metric_activation.event_activation(j);
+            auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
+            if (logTrackerIt == logEventTrackerMap.end()) {
+                ALOGE("Atom matcher not found for event activation.");
+                return false;
+            }
+            const int atomMatcherIndex = logTrackerIt->second;
+            activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
+                metricTrackerIndex);
+            allMetricProducers[metricTrackerIndex]->addActivation(
+                atomMatcherIndex, activation.ttl_seconds());
+        }
+    }
+    return true;
+}
+
 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
                       const sp<StatsPullerManager>& pullerManager,
                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -698,6 +736,8 @@
                       unordered_map<int, std::vector<int>>& conditionToMetricMap,
                       unordered_map<int, std::vector<int>>& trackerToMetricMap,
                       unordered_map<int, std::vector<int>>& trackerToConditionMap,
+                      unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+                      vector<int>& metricsWithActivation,
                       std::set<int64_t>& noReportMetricIds) {
     unordered_map<int64_t, int> logTrackerMap;
     unordered_map<int64_t, int> conditionTrackerMap;
@@ -732,6 +772,11 @@
         ALOGE("initAlarms failed");
         return false;
     }
+    if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
+            allMetricProducers, activationAtomTrackerToMetricMap, metricsWithActivation)) {
+        ALOGE("initMetricActivations failed");
+        return false;
+    }
 
     return true;
 }
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index c660149..9ffceda 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -108,6 +108,8 @@
                       std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
                       std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
                       std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+                      unordered_map<int, std::vector<int>>& lifeSpanEventTrackerToMetricMap,
+                      vector<int>& metricsWithLifeSpan,
                       std::set<int64_t>& noReportMetricIds);
 
 bool isStateTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys);
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d19e247..d5f81a59 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -347,6 +347,17 @@
   optional float probability_of_informing = 7 [default = 1.1];
 }
 
+message EventActivation {
+  optional int64 atom_matcher_id = 1;
+  optional int64 ttl_seconds = 2;
+}
+
+message MetricActivation {
+  optional int64 metric_id = 1;
+
+  repeated EventActivation event_activation = 2;
+}
+
 message StatsdConfig {
   optional int64 id = 1;
 
@@ -384,6 +395,8 @@
 
   optional bool hash_strings_in_metric_report = 16 [default = true];
 
+  repeated MetricActivation metric_activation = 17;
+
   // Field number 1000 is reserved for later use.
   reserved 1000;
 }
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 8fbb58a..f8184d8 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -282,13 +282,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                  periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                  allAtomMatchers, allConditionTrackers, allMetricProducers,
                                  allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                 trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                 trackerToMetricMap, trackerToConditionMap,
+                                 lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                 noReportMetricIds));
     EXPECT_EQ(1u, allMetricProducers.size());
     EXPECT_EQ(1u, allAnomalyTrackers.size());
     EXPECT_EQ(1u, noReportMetricIds.size());
@@ -309,13 +313,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
@@ -333,13 +341,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestMissingMatchers) {
@@ -357,12 +369,16 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestMissingPredicate) {
@@ -380,12 +396,16 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestCirclePredicateDependency) {
@@ -403,13 +423,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
@@ -427,13 +451,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 #else
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
new file mode 100644
index 0000000..0f13a4a
--- /dev/null
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -0,0 +1,242 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateStatsdConfig() {
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+    auto crashMatcher = CreateProcessCrashAtomMatcher();
+    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+    auto saverModeMatcher = CreateBatterySaverModeStartAtomMatcher();
+
+    *config.add_atom_matcher() = saverModeMatcher;
+    *config.add_atom_matcher() = crashMatcher;
+    *config.add_atom_matcher() = screenOnMatcher;
+
+    int64_t metricId = 123456;
+    auto countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(crashMatcher.id());
+    countMetric->set_bucket(FIVE_MINUTES);
+    countMetric->mutable_dimensions_in_what()->set_field(
+        android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+    countMetric->mutable_dimensions_in_what()->add_child()->set_field(1);  // uid field
+
+    auto metric_activation1 = config.add_metric_activation();
+    metric_activation1->set_metric_id(metricId);
+    auto event_activation1 = metric_activation1->add_event_activation();
+    event_activation1->set_atom_matcher_id(saverModeMatcher.id());
+    event_activation1->set_ttl_seconds(60 * 6);  // 6 minutes
+    auto event_activation2 = metric_activation1->add_event_activation();
+    event_activation2->set_atom_matcher_id(screenOnMatcher.id());
+    event_activation2->set_ttl_seconds(60 * 2);  // 2 minutes
+
+    return config;
+}
+
+}  // namespace
+
+TEST(MetricActivationE2eTest, TestCountMetric) {
+    auto config = CreateStatsdConfig();
+
+    int64_t bucketStartTimeNs = 10000000000;
+    int64_t bucketSizeNs =
+        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+
+    ConfigKey cfgKey;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    sp<MetricProducer> metricProducer =
+        processor->mMetricsManagers.begin()->second->mAllMetricProducers[0];
+    auto& eventActivationMap = metricProducer->mEventActivationMap;
+
+    EXPECT_FALSE(metricProducer->mIsActive);
+    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+    // triggered by screen on event (tracker index 2).
+    EXPECT_EQ(eventActivationMap.size(), 2u);
+    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    std::unique_ptr<LogEvent> event;
+
+    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+    processor->OnLogEvent(event.get());
+    EXPECT_FALSE(metricProducer->mIsActive);
+
+    // Activated by battery save mode.
+    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // First processed event.
+    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+    processor->OnLogEvent(event.get());
+
+    // Activated by screen on event.
+    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + 20);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // 2nd processed event.
+    // The activation by screen_on event expires, but the one by battery save mode is still active.
+    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // 3rd processed event.
+    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+    processor->OnLogEvent(event.get());
+
+    // All activations expired.
+    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+    processor->OnLogEvent(event.get());
+    EXPECT_FALSE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // Re-activate.
+    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+    processor->OnLogEvent(event.get());
+
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, ADB_DUMP,
+                            &buffer);
+    EXPECT_TRUE(buffer.size() > 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStartEndTimestamp(&reports);
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
+
+    StatsLogReport::CountMetricDataWrapper countMetrics;
+    sortMetricDataByDimensionsValue(
+            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+    EXPECT_EQ(4, countMetrics.data_size());
+
+    auto data = countMetrics.data(0);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(1);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(2);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    // Partial bucket as metric is deactivated.
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(3);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+}
+
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3c9a2d4..94b42ff 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -195,6 +195,13 @@
     private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";
 
     /**
+     * See {@link #setPendingIntentLaunchFlags(int)}
+     * @hide
+     */
+    private static final String KEY_PENDING_INTENT_LAUNCH_FLAGS =
+            "android.activity.pendingIntentLaunchFlags";
+
+    /**
      * See {@link #setTaskOverlay}.
      * @hide
      */
@@ -309,6 +316,7 @@
     @WindowConfiguration.ActivityType
     private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
     private int mLaunchTaskId = -1;
+    private int mPendingIntentLaunchFlags;
     private int mSplitScreenCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
     private boolean mLockTaskMode = false;
     private boolean mDisallowEnterPictureInPictureWhileLaunching;
@@ -932,6 +940,7 @@
         mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
         mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
         mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
+        mPendingIntentLaunchFlags = opts.getInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, 0);
         mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
         mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
         mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
@@ -1233,6 +1242,22 @@
     }
 
     /**
+     * Specifies intent flags to be applied for any activity started from a PendingIntent.
+     *
+     * @hide
+     */
+    public void setPendingIntentLaunchFlags(@android.content.Intent.Flags int flags) {
+        mPendingIntentLaunchFlags = flags;
+    }
+
+    /**
+     * @hide
+     */
+    public int getPendingIntentLaunchFlags() {
+        return mPendingIntentLaunchFlags;
+    }
+
+    /**
      * Set's whether the activity launched with this option should be a task overlay. That is the
      * activity will always be the top activity of the task.  If {@param canResume} is true, then
      * the task will also not be moved to the front of the stack.
@@ -1463,6 +1488,9 @@
         if (mLaunchTaskId != -1) {
             b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
         }
+        if (mPendingIntentLaunchFlags != 0) {
+            b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);
+        }
         if (mTaskOverlay) {
             b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
         }
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 384115b..0c56d48 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.opengl.EGL14;
 import android.os.Build;
@@ -30,6 +31,7 @@
 
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -54,6 +56,7 @@
     private static final String PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
     private static final String ANGLE_PACKAGE_NAME = "com.android.angle";
     private static final String GLES_MODE_METADATA_KEY = "com.android.angle.GLES_MODE";
+    private static final String ANGLE_RULES_FILE = "a4a_rules.json";
 
     private ClassLoader mClassLoader;
     private String mLayerPath;
@@ -250,8 +253,40 @@
 
         if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
 
+        // Pass the rules file to loader for ANGLE decisions
+        AssetManager angleAssets = null;
+        try {
+            angleAssets =
+                context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
+            return;
+        }
+
+        AssetFileDescriptor assetsFd = null;
+        try {
+            assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
+                       + "'" + ANGLE_PACKAGE_NAME + "'");
+            return;
+        }
+
+        FileDescriptor rulesFd = null;
+        long rulesOffset = 0;
+        long rulesLength = 0;
+        if (assetsFd != null) {
+            rulesFd = assetsFd.getFileDescriptor();
+            rulesOffset = assetsFd.getStartOffset();
+            rulesLength = assetsFd.getLength();
+        } else {
+            Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
+            return;
+        }
+
         // Further opt-in logic is handled in native, so pass relevant info down
-        setAngleInfo(paths, packageName, appPref, devOptIn);
+        setAngleInfo(paths, packageName, appPref, devOptIn,
+                     rulesFd, rulesOffset, rulesLength);
     }
 
     /**
@@ -391,5 +426,6 @@
     private static native void setDebugLayers(String layers);
     private static native void setDriverPath(String path);
     private static native void setAngleInfo(String path, String appPackage, String appPref,
-                                            boolean devOptIn);
+                                            boolean devOptIn, FileDescriptor rulesFd,
+                                            long rulesOffset, long rulesLength);
 }
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index bdd7a09..69d7202 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -282,19 +282,28 @@
             SAFE_BROWSING_THREAT_UNKNOWN,
             SAFE_BROWSING_THREAT_MALWARE,
             SAFE_BROWSING_THREAT_PHISHING,
-            SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE
+            SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE,
+            SAFE_BROWSING_THREAT_BILLING,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SafeBrowsingThreat {}
 
-    /** The resource was blocked for an unknown reason */
+    /** The resource was blocked for an unknown reason. */
     public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0;
-    /** The resource was blocked because it contains malware */
+    /** The resource was blocked because it contains malware. */
     public static final int SAFE_BROWSING_THREAT_MALWARE = 1;
-    /** The resource was blocked because it contains deceptive content */
+    /** The resource was blocked because it contains deceptive content. */
     public static final int SAFE_BROWSING_THREAT_PHISHING = 2;
-    /** The resource was blocked because it contains unwanted software */
+    /** The resource was blocked because it contains unwanted software. */
     public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = 3;
+    /**
+     * The resource was blocked because it may trick the user into a billing agreement.
+     *
+     * <p>This constant is only used when targetSdkVersion is greater than {@link
+     * android.os.Build.VERSION_CODES#Q}. Otherwise, {@link #SAFE_BROWSING_THREAT_UNKNOWN} is used
+     * instead.
+     */
+    public static final int SAFE_BROWSING_THREAT_BILLING = 4;
 
     /**
      * Report an error to the host application. These errors are unrecoverable
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 8f17e96..4d03123 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -370,10 +370,12 @@
                 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                 Context context = view.getContext();
                 ActivityOptions opts = getActivityOptions(context);
+                // The NEW_TASK flags are applied through the activity options and not as a part of
+                // the call to startIntentSender() to ensure that they are consistently applied to
+                // both mutable and immutable PendingIntents.
                 context.startIntentSender(
                         pendingIntent.getIntentSender(), fillInIntent,
-                        Intent.FLAG_ACTIVITY_NEW_TASK,
-                        Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
+                        0, 0, 0, opts.toBundle());
             } catch (IntentSender.SendIntentException e) {
                 android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
                 return false;
@@ -401,10 +403,15 @@
                 windowAnimationStyle.recycle();
 
                 if (enterAnimationId != 0) {
-                    return ActivityOptions.makeCustomAnimation(context, enterAnimationId, 0);
+                    final ActivityOptions opts = ActivityOptions.makeCustomAnimation(context,
+                            enterAnimationId, 0);
+                    opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    return opts;
                 }
             }
-            return ActivityOptions.makeBasic();
+            final ActivityOptions opts = ActivityOptions.makeBasic();
+            opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            return opts;
         }
     }
 
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 92235ad..e64da5c 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,12 +32,16 @@
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
 }
 
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn) {
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn,
+                         jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
     ScopedUtfChars pathChars(env, path);
     ScopedUtfChars appNameChars(env, appName);
     ScopedUtfChars appPrefChars(env, appPref);
+
+    int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
+
     android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
-            appPrefChars.c_str(), devOptIn);
+            appPrefChars.c_str(), devOptIn, rulesFd_native, rulesOffset, rulesLength);
 }
 
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -57,7 +61,7 @@
 const JNINativeMethod g_methods[] = {
     { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
-    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", reinterpret_cast<void*>(setAngleInfo_native) },
+    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
     { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
 };
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index c98e646..7360e9f 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -20,7 +20,6 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
@@ -239,7 +238,6 @@
     }
 
     @Test
-    @Suppress
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
@@ -256,20 +254,15 @@
         // Isolated multiple emoji modifier
         state.setByString("| U+1F3FB U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
 
         // Multiple emoji modifiers
         state.setByString("| U+1F466 U+1F3FB U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
     }
 
     @Test
-    @Suppress
     public void testMixedEdgeCases() {
         EditorState state = new EditorState();
 
@@ -318,7 +311,7 @@
         // COMBINING ENCLOSING KEYCAP + emoji modifier
         state.setByString("| '1' U+20E3 U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // Emoji modifier + COMBINING ENCLOSING KEYCAP
         state.setByString("| U+1F466 U+1F3FB U+20E3");
@@ -360,7 +353,7 @@
         // Variation selector + emoji modifier
         state.setByString("| U+2665 U+FE0F U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // Emoji modifier + variation selector
         state.setByString("| U+1F466 U+1F3FB U+FE0F");
@@ -396,7 +389,7 @@
         // Start with ZERO WIDTH JOINER + emoji modifier
         state.setByString("| U+200D U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // ZERO WIDTH JOINER + emoji modifier
         state.setByString("| U+1F469 U+200D U+1F3FB");
@@ -418,8 +411,6 @@
         // Regional indicator symbol + emoji modifier
         state.setByString("| U+1F1FA U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
 
         // Emoji modifier + regional indicator symbol
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index a0da330..71df7dc 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -738,59 +738,67 @@
             @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies,
             long startPos, long endPos)
             throws IOException {
-        // The context and URI usually belong to the calling user. Get a resolver for that user
-        // and strip out the userId from the URI if present.
+        // The context and URI usually belong to the calling user. Get a resolver for that user.
         final ContentResolver resolver = context.getContentResolver();
         final String scheme = uri.getScheme();
-        final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
         if (ContentResolver.SCHEME_FILE.equals(scheme)) {
             handleDataSource(isCurrent, srcId, uri.getPath(), null, null, startPos, endPos);
             return;
         }
 
-        AssetFileDescriptor afd = null;
+        final int ringToneType = RingtoneManager.getDefaultType(uri);
         try {
+            AssetFileDescriptor afd;
             // Try requested Uri locally first
-            if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                    && Settings.AUTHORITY.equals(authority)) {
+            if (ContentResolver.SCHEME_CONTENT.equals(scheme) && ringToneType != -1) {
                 afd = RingtoneManager.openDefaultRingtoneUri(context, uri);
+                if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
+                    return;
+                }
+                final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(
+                        context, ringToneType);
+                afd = resolver.openAssetFileDescriptor(actualUri, "r");
             } else {
                 afd = resolver.openAssetFileDescriptor(uri, "r");
             }
-            if (afd != null) {
-                handleDataSource(isCurrent, srcId, afd, startPos, endPos);
+            if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
                 return;
             }
         } catch (NullPointerException | SecurityException | IOException ex) {
             Log.w(TAG, "Couldn't open " + uri + ": " + ex);
             // Fallback to media server
-        } finally {
-            if (afd != null) {
-                afd.close();
-            }
         }
         handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies, startPos, endPos);
     }
 
-    private void handleDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd,
-            long startPos, long endPos)
-            throws IOException {
-        if (afd.getDeclaredLength() < 0) {
-            handleDataSource(isCurrent,
-                    srcId,
-                    afd.getFileDescriptor(),
-                    0,
-                    DataSourceDesc.LONG_MAX,
-                    startPos,
-                    endPos);
-        } else {
-            handleDataSource(isCurrent,
-                    srcId,
-                    afd.getFileDescriptor(),
-                    afd.getStartOffset(),
-                    afd.getDeclaredLength(),
-                    startPos,
-                    endPos);
+    private boolean attemptDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd,
+            long startPos, long endPos) throws IOException {
+        try {
+            if (afd.getDeclaredLength() < 0) {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        0,
+                        DataSourceDesc.LONG_MAX,
+                        startPos,
+                        endPos);
+            } else {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength(),
+                        startPos,
+                        endPos);
+            }
+            return true;
+        } catch (NullPointerException | SecurityException | IOException ex) {
+            Log.w(TAG, "Couldn't open srcId:" + srcId + ": " + ex);
+            return false;
+        } finally {
+            if (afd != null) {
+                afd.close();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 3bdd601..cc9adb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5277,8 +5277,7 @@
             (Runnable saveImportance, StatusBarNotification sbn) -> {
                 // If the user has security enabled, show challenge if the setting is changed.
                 if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
-                        && (mState == StatusBarState.KEYGUARD ||
-                                mState == StatusBarState.SHADE_LOCKED)) {
+                        && mKeyguardManager.isKeyguardLocked()) {
                     onLockedNotificationImportanceChange(() -> {
                         saveImportance.run();
                         return true;
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index b9c6fa6..2dcddff 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -288,12 +288,19 @@
                 resolvedType = key.requestResolvedType;
             }
 
+            // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
+            // can specify a consistent launch mode even if the PendingIntent is immutable
+            final ActivityOptions opts = ActivityOptions.fromBundle(options);
+            if (opts != null) {
+                finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
+            }
+
             // Extract options before clearing calling identity
             mergedOptions = key.options;
             if (mergedOptions == null) {
-                mergedOptions = SafeActivityOptions.fromBundle(options);
+                mergedOptions = new SafeActivityOptions(opts);
             } else {
-                mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
+                mergedOptions.setCallerOptions(opts);
             }
 
             if (whitelistDuration != null) {