Merge "Revert "Remove obsolete AndroidTestCase""
diff --git a/Android.mk b/Android.mk
index ba153ee..770ec20 100644
--- a/Android.mk
+++ b/Android.mk
@@ -113,6 +113,17 @@
 	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))
 	$(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))
 
+$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): \
+    frameworks/base/tools/hiddenapi/merge_csv.py \
+    $(PRIVATE_METADATA_INPUTS)
+	frameworks/base/tools/hiddenapi/merge_csv.py $(PRIVATE_METADATA_INPUTS) > $@
+
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST))
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA))
+
 # Include subdirectory makefiles
 # ============================================================
 
diff --git a/api/current.txt b/api/current.txt
index 71793c0..878e2e8 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -43439,7 +43439,8 @@
 
 package android.telephony.emergency {
 
-  public final class EmergencyNumber implements android.os.Parcelable {
+  public final class EmergencyNumber implements java.lang.Comparable android.os.Parcelable {
+    method public int compareTo(android.telephony.emergency.EmergencyNumber);
     method public int describeContents();
     method public java.lang.String getCountryIso();
     method public int getEmergencyNumberSourceBitmask();
diff --git a/api/system-current.txt b/api/system-current.txt
index 87a44ce..ab79107 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5604,17 +5604,12 @@
   }
 
   public final class DataProfile implements android.os.Parcelable {
-    ctor public DataProfile(int, java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, int, int, int, int, boolean, int, java.lang.String, int, int, java.lang.String, java.lang.String, boolean);
-    ctor public DataProfile(android.os.Parcel);
-    method public int describeContents();
     method public java.lang.String getApn();
     method public int getAuthType();
     method public int getBearerBitmap();
     method public int getMaxConns();
     method public int getMaxConnsTime();
     method public int getMtu();
-    method public java.lang.String getMvnoMatchData();
-    method public java.lang.String getMvnoType();
     method public java.lang.String getPassword();
     method public int getProfileId();
     method public java.lang.String getProtocol();
@@ -5624,9 +5619,8 @@
     method public java.lang.String getUserName();
     method public int getWaitTime();
     method public boolean isEnabled();
-    method public boolean isModemCognitive();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR;
+    method public boolean isPersistent();
+    method public boolean isPreferred();
     field public static final int TYPE_3GPP = 1; // 0x1
     field public static final int TYPE_3GPP2 = 2; // 0x2
     field public static final int TYPE_COMMON = 0; // 0x0
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index c396cd1..2f05a52 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -46,6 +46,7 @@
     src/logd/LogEvent.cpp \
     src/logd/LogListener.cpp \
     src/matchers/CombinationLogMatchingTracker.cpp \
+    src/matchers/EventMatcherWizard.cpp \
     src/matchers/matcher_util.cpp \
     src/matchers/SimpleLogMatchingTracker.cpp \
     src/metrics/MetricProducer.cpp \
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 6a9e8a1..3eb83b4 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -194,7 +194,7 @@
     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
-    FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
+    FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents);
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
 
diff --git a/cmds/statsd/src/matchers/EventMatcherWizard.cpp b/cmds/statsd/src/matchers/EventMatcherWizard.cpp
new file mode 100644
index 0000000..8418e98
--- /dev/null
+++ b/cmds/statsd/src/matchers/EventMatcherWizard.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "EventMatcherWizard.h"
+#include <unordered_set>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::map;
+using std::string;
+using std::vector;
+
+MatchingState EventMatcherWizard::matchLogEvent(const LogEvent& event, int matcher_index) {
+    if (matcher_index < 0 || matcher_index >= (int)mAllEventMatchers.size()) {
+        return MatchingState::kNotComputed;
+    }
+    vector<MatchingState> matcherCache(mAllEventMatchers.size(), MatchingState::kNotComputed);
+    mAllEventMatchers[matcher_index]->onLogEvent(event, mAllEventMatchers, matcherCache);
+    return matcherCache[matcher_index];
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
\ No newline at end of file
diff --git a/cmds/statsd/src/matchers/EventMatcherWizard.h b/cmds/statsd/src/matchers/EventMatcherWizard.h
new file mode 100644
index 0000000..57ec2b3
--- /dev/null
+++ b/cmds/statsd/src/matchers/EventMatcherWizard.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "LogMatchingTracker.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class EventMatcherWizard : public virtual android::RefBase {
+public:
+    EventMatcherWizard(){};  // for testing
+    EventMatcherWizard(const std::vector<sp<LogMatchingTracker>>& eventTrackers)
+        : mAllEventMatchers(eventTrackers){};
+
+    virtual ~EventMatcherWizard(){};
+
+    MatchingState matchLogEvent(const LogEvent& event, int matcher_index);
+
+private:
+    std::vector<sp<LogMatchingTracker>> mAllEventMatchers;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 02b9773..f5a16e9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -69,11 +69,16 @@
 
 GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& metric,
                                          const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard, const int pullTagId,
+                                         const sp<ConditionWizard>& wizard,
+                                         const int whatMatcherIndex,
+                                         const sp<EventMatcherWizard>& matcherWizard,
+                                         const int pullTagId,
                                          const int triggerAtomId, const int atomId,
                                          const int64_t timeBaseNs, const int64_t startTimeNs,
                                          const sp<StatsPullerManager>& pullerManager)
     : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+      mWhatMatcherIndex(whatMatcherIndex),
+      mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
       mPullTagId(pullTagId),
       mTriggerAtomId(triggerAtomId),
@@ -136,7 +141,7 @@
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
     if (mIsPulled) {
-        pullLocked(startTimeNs);
+        pullAndMatchEventsLocked(startTimeNs);
     }
 
     VLOG("Gauge metric %lld created. bucket size %lld start_time: %lld sliced %d",
@@ -302,7 +307,7 @@
     mPastBuckets.clear();
 }
 
-void GaugeMetricProducer::pullLocked(const int64_t timestampNs) {
+void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
     bool triggerPuller = false;
     switch(mSamplingType) {
         // When the metric wants to do random sampling and there is already one gauge atom for the
@@ -331,7 +336,10 @@
         return;
     }
     for (const auto& data : allData) {
-        onMatchedLogEventLocked(0, *data);
+        if (mEventMatcherWizard->matchLogEvent(
+                *data, mWhatMatcherIndex) == MatchingState::kMatched) {
+            onMatchedLogEventLocked(mWhatMatcherIndex, *data);
+        }
     }
 }
 
@@ -341,7 +349,7 @@
     flushIfNeededLocked(eventTimeNs);
     mCondition = conditionMet;
     if (mIsPulled) {
-        pullLocked(eventTimeNs);
+        pullAndMatchEventsLocked(eventTimeNs);
     }  // else: Push mode. No need to proactively pull the gauge data.
 }
 
@@ -354,7 +362,7 @@
     // pull for every dimension.
     mCondition = overallCondition;
     if (mIsPulled) {
-        pullLocked(eventTimeNs);
+        pullAndMatchEventsLocked(eventTimeNs);
     }  // else: Push mode. No need to proactively pull the gauge data.
 }
 
@@ -387,7 +395,10 @@
         return;
     }
     for (const auto& data : allData) {
-        onMatchedLogEventLocked(0, *data);
+        if (mEventMatcherWizard->matchLogEvent(
+                *data, mWhatMatcherIndex) == MatchingState::kMatched) {
+            onMatchedLogEventLocked(mWhatMatcherIndex, *data);
+        }
     }
 }
 
@@ -426,7 +437,7 @@
     flushIfNeededLocked(eventTimeNs);
 
     if (mTriggerAtomId == event.GetTagId()) {
-        pullLocked(eventTimeNs);
+        pullAndMatchEventsLocked(eventTimeNs);
         return;
     }
 
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 6379389..99827bb 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -24,6 +24,7 @@
 #include "../external/PullDataReceiver.h"
 #include "../external/StatsPullerManager.h"
 #include "../matchers/matcher_util.h"
+#include "../matchers/EventMatcherWizard.h"
 #include "MetricProducer.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "../stats_util.h"
@@ -56,7 +57,9 @@
 class GaugeMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
 public:
     GaugeMetricProducer(const ConfigKey& key, const GaugeMetric& gaugeMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& wizard,
+                        const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
+                        const int whatMatcherIndex,
+                        const sp<EventMatcherWizard>& matcherWizard,
                         const int pullTagId, const int triggerAtomId, const int atomId,
                         const int64_t timeBaseNs, const int64_t startTimeNs,
                         const sp<StatsPullerManager>& pullerManager);
@@ -78,7 +81,7 @@
         flushCurrentBucketLocked(eventTimeNs);
         mCurrentBucketStartTimeNs = eventTimeNs;
         if (mIsPulled) {
-            pullLocked(eventTimeNs);
+            pullAndMatchEventsLocked(eventTimeNs);
         }
     };
 
@@ -113,7 +116,11 @@
 
     void flushCurrentBucketLocked(const int64_t& eventTimeNs) override;
 
-    void pullLocked(const int64_t timestampNs);
+    void pullAndMatchEventsLocked(const int64_t timestampNs);
+
+    const int mWhatMatcherIndex;
+
+    sp<EventMatcherWizard> mEventMatcherWizard;
 
     sp<StatsPullerManager> mPullerManager;
     // tagId for pulled data. -1 if this is not pulled
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index dfbb69f..e8029a2 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -207,7 +207,7 @@
     FRIEND_TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
-    FRIEND_TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents);
+    FRIEND_TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents);
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
     FRIEND_TEST(DimensionInConditionE2eTest, TestCreateCountMetric_NoLink_OR_CombinationCondition);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 75d6df9..481099a 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -25,6 +25,7 @@
 #include "../external/StatsPullerManager.h"
 #include "../matchers/CombinationLogMatchingTracker.h"
 #include "../matchers/SimpleLogMatchingTracker.h"
+#include "../matchers/EventMatcherWizard.h"
 #include "../metrics/CountMetricProducer.h"
 #include "../metrics/DurationMetricProducer.h"
 #include "../metrics/EventMetricProducer.h"
@@ -294,6 +295,7 @@
                  unordered_map<int, std::vector<int>>& trackerToMetricMap,
                  unordered_map<int64_t, int>& metricMap, std::set<int64_t>& noReportMetricIds) {
     sp<ConditionWizard> wizard = new ConditionWizard(allConditionTrackers);
+    sp<EventMatcherWizard> matcherWizard = new EventMatcherWizard(allAtomMatchers);
     const int allMetricsCount = config.count_metric_size() + config.duration_metric_size() +
                                 config.event_metric_size() + config.value_metric_size();
     allMetricProducers.reserve(allMetricsCount);
@@ -563,7 +565,8 @@
         }
 
         sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
-                key, metric, conditionIndex, wizard, pullTagId, triggerAtomId, atomTagId,
+                key, metric, conditionIndex, wizard,
+                trackerIndex, matcherWizard, pullTagId, triggerAtomId, atomTagId,
                 timeBaseTimeNs, currentTimeNs, pullerManager);
         allMetricProducers.push_back(gaugeProducer);
     }
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 5729feb..d7b9c11 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -200,8 +200,8 @@
     EXPECT_GT(data.bucket_info(5).atom(0).temperature().temperature_deci_celsius(), 0);
 }
 
-TEST(GaugeMetricE2eTest, TestAllConditionChangesSamplePulledEvents) {
-    auto config = CreateStatsdConfig(GaugeMetric::ALL_CONDITION_CHANGES);
+TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
+    auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
     int64_t baseTimeNs = 10 * NS_PER_SEC;
     int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
     int64_t bucketSizeNs =
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index bf58b9c..60bd4a7 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/matchers/SimpleLogMatchingTracker.h"
 #include "src/metrics/GaugeMetricProducer.h"
 #include "src/stats_log_util.h"
 #include "logd/LogEvent.h"
@@ -40,6 +41,8 @@
 const ConfigKey kConfigKey(0, 12345);
 const int tagId = 1;
 const int64_t metricId = 123;
+const int64_t atomMatcherId = 678;
+const int logEventMatcherIndex = 0;
 const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
@@ -61,11 +64,19 @@
     gaugeFieldMatcher->add_child()->set_field(3);
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
     // statsd started long ago.
     // The metric starts in the middle of the bucket
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       -1, -1, tagId, 5, 600 * NS_PER_SEC + NS_PER_SEC / 2,
                                       pullerManager);
 
@@ -86,6 +97,12 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
@@ -103,6 +120,7 @@
             }));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
@@ -178,7 +196,15 @@
     alert.set_num_buckets(100);
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
 
@@ -246,6 +272,12 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
@@ -263,6 +295,7 @@
             }));
 
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
@@ -315,6 +348,12 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
@@ -330,7 +369,8 @@
                 return true;
             }));
 
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, -1, tagId,
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
@@ -388,6 +428,12 @@
     dim->set_field(conditionTag);
     dim->add_child()->set_field(1);
 
+    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>();
     EXPECT_CALL(*wizard, query(_, _, _, _, _, _))
             .WillRepeatedly(
@@ -420,7 +466,8 @@
                 return true;
             }));
 
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard, tagId, -1, tagId,
+    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
                                       bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
@@ -463,7 +510,15 @@
     auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
     gaugeFieldMatcher->set_field(tagId);
     gaugeFieldMatcher->add_child()->set_field(2);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
@@ -542,6 +597,12 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
@@ -574,6 +635,7 @@
 
     int triggerId = 5;
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
@@ -632,6 +694,12 @@
 
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
@@ -667,6 +735,7 @@
 
     int triggerId = 5;
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard,
                                       tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
                                       pullerManager);
 
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index a9cb0d9..f71fdd7 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1198,6 +1198,19 @@
 
     /** {@hide} */
     public static int translateModeStringToPosix(String mode) {
+        // Sanity check for invalid chars
+        for (int i = 0; i < mode.length(); i++) {
+            switch (mode.charAt(i)) {
+                case 'r':
+                case 'w':
+                case 't':
+                case 'a':
+                    break;
+                default:
+                    throw new IllegalArgumentException("Bad mode: " + mode);
+            }
+        }
+
         int res = 0;
         if (mode.startsWith("rw")) {
             res |= O_RDWR | O_CREAT;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 22bce1d..ad64021 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12381,6 +12381,28 @@
                 "sms_access_restriction_enabled";
 
         /**
+         * If set to 1, an app must have the READ_PRIVILEGED_PHONE_STATE permission (or be a device
+         * / profile owner with the READ_PHONE_STATE permission) to access device identifiers.
+         *
+         * STOPSHIP: Remove this once we ship with the new device identifier check enabled.
+         *
+         * @hide
+         */
+        public static final String PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED =
+                "privileged_device_identifier_check_enabled";
+
+        /**
+         * If set to 1, an app that is targeting Q and does not meet the new requirements to access
+         * device identifiers will receive a SecurityException.
+         *
+         * STOPSHIP: Remove this once we ship with the new device identifier check enabled.
+         *
+         * @hide
+         */
+        public static final String PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED =
+                "privileged_device_identifier_target_q_behavior_enabled";
+
+        /**
          * If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will be ignored
          * and restoring to lower version of platform API will be skipped.
          *
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ed6445d..5e62fd3 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -239,6 +239,7 @@
 
     shared_libs: [
         "libbpf",
+        "libnetdbpf",
         "libnetdutils",
         "libmemtrack",
         "libandroidfw",
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 2619107..bb291e7 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -23,8 +23,6 @@
 #include <hwui/Paint.h>
 #include <utils/Log.h>
 
-#include <ResourceCache.h>
-
 #include "SkCanvas.h"
 #include "SkLatticeIter.h"
 #include "SkRegion.h"
@@ -83,12 +81,7 @@
 
     static void finalize(JNIEnv* env, jobject, jlong patchHandle) {
         int8_t* patch = reinterpret_cast<int8_t*>(patchHandle);
-        if (android::uirenderer::ResourceCache::hasInstance()) {
-            Res_png_9patch* p = (Res_png_9patch*) patch;
-            android::uirenderer::ResourceCache::getInstance().destructor(p);
-        } else {
-            delete[] patch;
-        }
+        delete[] patch;
     }
 
     static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap,
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 109e65c..b3ff4db 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -32,8 +32,8 @@
 #include <utils/misc.h>
 
 #include "android-base/unique_fd.h"
-#include "bpf/BpfNetworkStats.h"
 #include "bpf/BpfUtils.h"
+#include "netdbpf/BpfNetworkStats.h"
 
 using android::bpf::hasBpfSupport;
 using android::bpf::parseBpfNetworkStatsDetail;
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 80281b6..6966448 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -41,6 +41,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.os.FileUtils.MemoryPipe;
@@ -510,6 +511,20 @@
                 MODE_WRITE_ONLY | MODE_CREATE | MODE_APPEND);
     }
 
+    @Test
+    public void testTranslateMode_Invalid() throws Exception {
+        try {
+            translateModeStringToPosix("rwx");
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            translateModeStringToPosix("");
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     private static void assertTranslate(String string, int posix, int pfd) {
         assertEquals(posix, translateModeStringToPosix(string));
         assertEquals(string, translateModePosixToString(posix));
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 632c37f..9778acb 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -368,6 +368,8 @@
                     Settings.Global.PRIV_APP_OOB_ENABLED,
                     Settings.Global.PRIV_APP_OOB_LIST,
                     Settings.Global.PRIVATE_DNS_DEFAULT_MODE,
+                    Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED,
+                    Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED,
                     Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
                     Settings.Global.RADIO_BLUETOOTH,
                     Settings.Global.RADIO_CELL,
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index e3ec45b..503951d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -202,9 +202,7 @@
         "AnimationContext.cpp",
         "Animator.cpp",
         "AnimatorManager.cpp",
-        "CanvasState.cpp",
         "CanvasTransform.cpp",
-        "ClipArea.cpp",
         "DamageAccumulator.cpp",
         "DeferredLayerUpdater.cpp",
         "DeviceInfo.cpp",
@@ -227,9 +225,7 @@
         "RecordingCanvas.cpp",
         "RenderNode.cpp",
         "RenderProperties.cpp",
-        "ResourceCache.cpp",
         "SkiaCanvas.cpp",
-        "Snapshot.cpp",
         "TreeInfo.cpp",
         "VectorDrawable.cpp",
         "protos/graphicsstats.proto",
@@ -308,8 +304,6 @@
         "tests/unit/main.cpp",
         "tests/unit/CacheManagerTests.cpp",
         "tests/unit/CanvasContextTests.cpp",
-        "tests/unit/CanvasStateTests.cpp",
-        "tests/unit/ClipAreaTests.cpp",
         "tests/unit/DamageAccumulatorTests.cpp",
         "tests/unit/DeferredLayerUpdaterTests.cpp",
         "tests/unit/FatVectorTests.cpp",
@@ -328,7 +322,6 @@
         "tests/unit/SkiaPipelineTests.cpp",
         "tests/unit/SkiaRenderPropertiesTests.cpp",
         "tests/unit/SkiaCanvasTests.cpp",
-        "tests/unit/SnapshotTests.cpp",
         "tests/unit/StringUtilsTests.cpp",
         "tests/unit/TestUtilsTests.cpp",
         "tests/unit/ThreadBaseTests.cpp",
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
deleted file mode 100644
index d18c4ab..0000000
--- a/libs/hwui/CanvasState.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "CanvasState.h"
-#include "hwui/Canvas.h"
-#include "utils/MathUtils.h"
-
-namespace android {
-namespace uirenderer {
-
-CanvasState::CanvasState(CanvasStateClient& renderer)
-        : mWidth(-1), mHeight(-1), mSaveCount(1), mCanvas(renderer), mSnapshot(&mFirstSnapshot) {}
-
-CanvasState::~CanvasState() {
-    // First call freeSnapshot on all but mFirstSnapshot
-    // to invoke all the dtors
-    freeAllSnapshots();
-
-    // Now actually release the memory
-    while (mSnapshotPool) {
-        void* temp = mSnapshotPool;
-        mSnapshotPool = mSnapshotPool->previous;
-        free(temp);
-    }
-}
-
-void CanvasState::initializeRecordingSaveStack(int viewportWidth, int viewportHeight) {
-    if (mWidth != viewportWidth || mHeight != viewportHeight) {
-        mWidth = viewportWidth;
-        mHeight = viewportHeight;
-        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
-        mCanvas.onViewportInitialized();
-    }
-
-    freeAllSnapshots();
-    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
-    mSnapshot->setRelativeLightCenter(Vector3());
-    mSaveCount = 1;
-}
-
-void CanvasState::initializeSaveStack(int viewportWidth, int viewportHeight, float clipLeft,
-                                      float clipTop, float clipRight, float clipBottom,
-                                      const Vector3& lightCenter) {
-    if (mWidth != viewportWidth || mHeight != viewportHeight) {
-        mWidth = viewportWidth;
-        mHeight = viewportHeight;
-        mFirstSnapshot.initializeViewport(viewportWidth, viewportHeight);
-        mCanvas.onViewportInitialized();
-    }
-
-    freeAllSnapshots();
-    mSnapshot = allocSnapshot(&mFirstSnapshot, SaveFlags::MatrixClip);
-    mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
-    mSnapshot->fbo = mCanvas.getTargetFbo();
-    mSnapshot->setRelativeLightCenter(lightCenter);
-    mSaveCount = 1;
-}
-
-Snapshot* CanvasState::allocSnapshot(Snapshot* previous, int savecount) {
-    void* memory;
-    if (mSnapshotPool) {
-        memory = mSnapshotPool;
-        mSnapshotPool = mSnapshotPool->previous;
-        mSnapshotPoolCount--;
-    } else {
-        memory = malloc(sizeof(Snapshot));
-    }
-    return new (memory) Snapshot(previous, savecount);
-}
-
-void CanvasState::freeSnapshot(Snapshot* snapshot) {
-    snapshot->~Snapshot();
-    // Arbitrary number, just don't let this grown unbounded
-    if (mSnapshotPoolCount > 10) {
-        free((void*)snapshot);
-    } else {
-        snapshot->previous = mSnapshotPool;
-        mSnapshotPool = snapshot;
-        mSnapshotPoolCount++;
-    }
-}
-
-void CanvasState::freeAllSnapshots() {
-    while (mSnapshot != &mFirstSnapshot) {
-        Snapshot* temp = mSnapshot;
-        mSnapshot = mSnapshot->previous;
-        freeSnapshot(temp);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Save (layer)
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Guaranteed to save without side-effects
- *
- * This approach, here and in restoreSnapshot(), allows subclasses to directly manipulate the save
- * stack, and ensures restoreToCount() doesn't call back into subclass overrides.
- */
-int CanvasState::saveSnapshot(int flags) {
-    mSnapshot = allocSnapshot(mSnapshot, flags);
-    return mSaveCount++;
-}
-
-int CanvasState::save(int flags) {
-    return saveSnapshot(flags);
-}
-
-/**
- * Guaranteed to restore without side-effects.
- */
-void CanvasState::restoreSnapshot() {
-    Snapshot* toRemove = mSnapshot;
-    Snapshot* toRestore = mSnapshot->previous;
-
-    mSaveCount--;
-    mSnapshot = toRestore;
-
-    // subclass handles restore implementation
-    mCanvas.onSnapshotRestored(*toRemove, *toRestore);
-
-    freeSnapshot(toRemove);
-}
-
-void CanvasState::restore() {
-    if (mSaveCount > 1) {
-        restoreSnapshot();
-    }
-}
-
-void CanvasState::restoreToCount(int saveCount) {
-    if (saveCount < 1) saveCount = 1;
-
-    while (mSaveCount > saveCount) {
-        restoreSnapshot();
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Matrix
-///////////////////////////////////////////////////////////////////////////////
-
-void CanvasState::getMatrix(SkMatrix* matrix) const {
-    mSnapshot->transform->copyTo(*matrix);
-}
-
-void CanvasState::translate(float dx, float dy, float dz) {
-    mSnapshot->transform->translate(dx, dy, dz);
-}
-
-void CanvasState::rotate(float degrees) {
-    mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f);
-}
-
-void CanvasState::scale(float sx, float sy) {
-    mSnapshot->transform->scale(sx, sy, 1.0f);
-}
-
-void CanvasState::skew(float sx, float sy) {
-    mSnapshot->transform->skew(sx, sy);
-}
-
-void CanvasState::setMatrix(const SkMatrix& matrix) {
-    mSnapshot->transform->load(matrix);
-}
-
-void CanvasState::setMatrix(const Matrix4& matrix) {
-    *(mSnapshot->transform) = matrix;
-}
-
-void CanvasState::concatMatrix(const SkMatrix& matrix) {
-    mat4 transform(matrix);
-    mSnapshot->transform->multiply(transform);
-}
-
-void CanvasState::concatMatrix(const Matrix4& matrix) {
-    mSnapshot->transform->multiply(matrix);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Clip
-///////////////////////////////////////////////////////////////////////////////
-
-bool CanvasState::clipRect(float left, float top, float right, float bottom, SkClipOp op) {
-    mSnapshot->clip(Rect(left, top, right, bottom), op);
-    return !mSnapshot->clipIsEmpty();
-}
-
-bool CanvasState::clipPath(const SkPath* path, SkClipOp op) {
-    mSnapshot->clipPath(*path, op);
-    return !mSnapshot->clipIsEmpty();
-}
-
-void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) {
-    Rect bounds;
-    float radius;
-    if (!outline->getAsRoundRect(&bounds, &radius)) return;  // only RR supported
-
-    bool outlineIsRounded = MathUtils::isPositive(radius);
-    if (!outlineIsRounded || currentTransform()->isSimple()) {
-        // TODO: consider storing this rect separately, so that this can't be replaced with clip ops
-        clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkClipOp::kIntersect);
-    }
-    if (outlineIsRounded) {
-        setClippingRoundRect(allocator, bounds, radius, false);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Quick Rejection
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Calculates whether content drawn within the passed bounds would be outside of, or intersect with
- * the clipRect. Does not modify the scissor.
- *
- * @param clipRequired if not null, will be set to true if element intersects clip
- *         (and wasn't rejected)
- *
- * @param snapOut if set, the geometry will be treated as having an AA ramp.
- *         See Rect::snapGeometryToPixelBoundaries()
- */
-bool CanvasState::calculateQuickRejectForScissor(float left, float top, float right, float bottom,
-                                                 bool* clipRequired, bool* roundRectClipRequired,
-                                                 bool snapOut) const {
-    if (bottom <= top || right <= left) {
-        return true;
-    }
-
-    Rect r(left, top, right, bottom);
-    currentTransform()->mapRect(r);
-    r.snapGeometryToPixelBoundaries(snapOut);
-
-    Rect clipRect(currentRenderTargetClip());
-    clipRect.snapToPixelBoundaries();
-
-    if (!clipRect.intersects(r)) return true;
-
-    // clip is required if geometry intersects clip rect
-    if (clipRequired) {
-        *clipRequired = !clipRect.contains(r);
-    }
-
-    // round rect clip is required if RR clip exists, and geometry intersects its corners
-    if (roundRectClipRequired) {
-        *roundRectClipRequired = mSnapshot->roundRectClipState != nullptr &&
-                                 mSnapshot->roundRectClipState->areaRequiresRoundRectClip(r);
-    }
-    return false;
-}
-
-bool CanvasState::quickRejectConservative(float left, float top, float right, float bottom) const {
-    if (bottom <= top || right <= left) {
-        return true;
-    }
-
-    Rect r(left, top, right, bottom);
-    currentTransform()->mapRect(r);
-    r.roundOut();  // rounded out to be conservative
-
-    Rect clipRect(currentRenderTargetClip());
-    clipRect.snapToPixelBoundaries();
-
-    if (!clipRect.intersects(r)) return true;
-
-    return false;
-}
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
deleted file mode 100644
index 9ac35ff..0000000
--- a/libs/hwui/CanvasState.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "Snapshot.h"
-
-#include <SkClipOp.h>
-#include <SkMatrix.h>
-#include <SkPath.h>
-#include <SkRegion.h>
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Abstract base class for any class containing CanvasState.
- * Defines three mandatory callbacks.
- */
-class CanvasStateClient {
-public:
-    CanvasStateClient() {}
-    virtual ~CanvasStateClient() {}
-
-    /**
-     * Callback allowing embedder to take actions in the middle of a
-     * setViewport() call.
-     */
-    virtual void onViewportInitialized() = 0;
-
-    /**
-     * Callback allowing embedder to take actions in the middle of a
-     * restore() call.  May be called several times sequentially.
-     */
-    virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) = 0;
-
-    /**
-     * Allows subclasses to control what value is stored in snapshot's
-     * fbo field in * initializeSaveStack.
-     */
-    virtual GLuint getTargetFbo() const = 0;
-
-};  // class CanvasStateClient
-
-/**
- * Implements Canvas state methods on behalf of Renderers.
- *
- * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
- * Renderer interface. Drawing and recording classes that include a CanvasState will have
- * different use cases:
- *
- * Drawing code maintaining canvas state (e.g. FrameBuilder) can query attributes (such as
- * transform) or hook into changes (e.g. save/restore) with minimal surface area for manipulating
- * the stack itself.
- *
- * Recording code maintaining canvas state (e.g. RecordingCanvas) can both record and pass
- * through state operations to CanvasState, so that not only will querying operations work
- * (getClip/Matrix), but so that quickRejection can also be used.
- */
-
-class CanvasState {
-public:
-    explicit CanvasState(CanvasStateClient& renderer);
-    ~CanvasState();
-
-    /**
-     * Initializes the first snapshot, computing the projection matrix,
-     * and stores the dimensions of the render target.
-     */
-    void initializeRecordingSaveStack(int viewportWidth, int viewportHeight);
-
-    /**
-     * Initializes the first snapshot, computing the projection matrix,
-     * and stores the dimensions of the render target.
-     */
-    void initializeSaveStack(int viewportWidth, int viewportHeight, float clipLeft, float clipTop,
-                             float clipRight, float clipBottom, const Vector3& lightCenter);
-
-    bool hasRectToRectTransform() const { return CC_LIKELY(currentTransform()->rectToRect()); }
-
-    // Save (layer)
-    int getSaveCount() const { return mSaveCount; }
-    int save(int flags);
-    void restore();
-    void restoreToCount(int saveCount);
-
-    // Save/Restore without side-effects
-    int saveSnapshot(int flags);
-    void restoreSnapshot();
-
-    // Matrix
-    void getMatrix(SkMatrix* outMatrix) const;
-    void translate(float dx, float dy, float dz = 0.0f);
-    void rotate(float degrees);
-    void scale(float sx, float sy);
-    void skew(float sx, float sy);
-
-    void setMatrix(const SkMatrix& matrix);
-    void setMatrix(const Matrix4& matrix);  // internal only convenience method
-    void concatMatrix(const SkMatrix& matrix);
-    void concatMatrix(const Matrix4& matrix);  // internal only convenience method
-
-    // Clip
-    const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
-    const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
-
-    bool quickRejectConservative(float left, float top, float right, float bottom) const;
-
-    bool clipRect(float left, float top, float right, float bottom, SkClipOp op);
-    bool clipPath(const SkPath* path, SkClipOp op);
-
-    /**
-     * Sets a "clipping outline", which is independent from the regular clip.
-     * Currently only supports rectangles or rounded rectangles; passing in a
-     * more complicated outline fails silently. Replaces any previous clipping
-     * outline.
-     */
-    void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
-    void setClippingRoundRect(LinearAllocator& allocator, const Rect& rect, float radius,
-                              bool highPriority = true) {
-        mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
-    }
-    void setProjectionPathMask(const SkPath* path) { mSnapshot->setProjectionPathMask(path); }
-
-    /**
-     * Returns true if drawing in the rectangle (left, top, right, bottom)
-     * will be clipped out. Is conservative: might return false when subpixel-
-     * perfect tests would return true.
-     */
-    bool calculateQuickRejectForScissor(float left, float top, float right, float bottom,
-                                        bool* clipRequired, bool* roundRectClipRequired,
-                                        bool snapOut) const;
-
-    void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; }
-
-    inline const mat4* currentTransform() const { return currentSnapshot()->transform; }
-    inline const Rect& currentRenderTargetClip() const {
-        return currentSnapshot()->getRenderTargetClip();
-    }
-    inline int currentFlags() const { return currentSnapshot()->flags; }
-    const Vector3& currentLightCenter() const {
-        return currentSnapshot()->getRelativeLightCenter();
-    }
-    int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); }
-    int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); }
-    int getWidth() const { return mWidth; }
-    int getHeight() const { return mHeight; }
-    bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
-
-    inline const Snapshot* currentSnapshot() const { return mSnapshot; }
-    inline Snapshot* writableSnapshot() { return mSnapshot; }
-    inline const Snapshot* firstSnapshot() const { return &mFirstSnapshot; }
-
-private:
-    Snapshot* allocSnapshot(Snapshot* previous, int savecount);
-    void freeSnapshot(Snapshot* snapshot);
-    void freeAllSnapshots();
-
-    /// Dimensions of the drawing surface
-    int mWidth, mHeight;
-
-    /// Number of saved states
-    int mSaveCount;
-
-    /// Base state
-    Snapshot mFirstSnapshot;
-
-    /// Host providing callbacks
-    CanvasStateClient& mCanvas;
-
-    /// Current state
-    Snapshot* mSnapshot;
-
-    // Pool of allocated snapshots to re-use
-    // NOTE: The dtors have already been invoked!
-    Snapshot* mSnapshotPool = nullptr;
-    int mSnapshotPoolCount = 0;
-
-};  // class CanvasState
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
deleted file mode 100644
index 27d93cf..0000000
--- a/libs/hwui/ClipArea.cpp
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * Copyright (C) 2015 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 "ClipArea.h"
-
-#include "utils/LinearAllocator.h"
-
-#include <SkPath.h>
-#include <limits>
-#include <type_traits>
-
-namespace android {
-namespace uirenderer {
-
-static void handlePoint(Rect& transformedBounds, const Matrix4& transform, float x, float y) {
-    Vertex v = {x, y};
-    transform.mapPoint(v.x, v.y);
-    transformedBounds.expandToCover(v.x, v.y);
-}
-
-Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) {
-    const float kMinFloat = std::numeric_limits<float>::lowest();
-    const float kMaxFloat = std::numeric_limits<float>::max();
-    Rect transformedBounds = {kMaxFloat, kMaxFloat, kMinFloat, kMinFloat};
-    handlePoint(transformedBounds, transform, r.left, r.top);
-    handlePoint(transformedBounds, transform, r.right, r.top);
-    handlePoint(transformedBounds, transform, r.left, r.bottom);
-    handlePoint(transformedBounds, transform, r.right, r.bottom);
-    return transformedBounds;
-}
-
-void ClipBase::dump() const {
-    ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect));
-}
-
-/*
- * TransformedRectangle
- */
-
-TransformedRectangle::TransformedRectangle() {}
-
-TransformedRectangle::TransformedRectangle(const Rect& bounds, const Matrix4& transform)
-        : mBounds(bounds), mTransform(transform) {}
-
-bool TransformedRectangle::canSimplyIntersectWith(const TransformedRectangle& other) const {
-    return mTransform == other.mTransform;
-}
-
-void TransformedRectangle::intersectWith(const TransformedRectangle& other) {
-    mBounds.doIntersect(other.mBounds);
-}
-
-bool TransformedRectangle::isEmpty() const {
-    return mBounds.isEmpty();
-}
-
-/*
- * RectangleList
- */
-
-RectangleList::RectangleList() : mTransformedRectanglesCount(0) {}
-
-bool RectangleList::isEmpty() const {
-    if (mTransformedRectanglesCount < 1) {
-        return true;
-    }
-
-    for (int i = 0; i < mTransformedRectanglesCount; i++) {
-        if (mTransformedRectangles[i].isEmpty()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-int RectangleList::getTransformedRectanglesCount() const {
-    return mTransformedRectanglesCount;
-}
-
-const TransformedRectangle& RectangleList::getTransformedRectangle(int i) const {
-    return mTransformedRectangles[i];
-}
-
-void RectangleList::setEmpty() {
-    mTransformedRectanglesCount = 0;
-}
-
-void RectangleList::set(const Rect& bounds, const Matrix4& transform) {
-    mTransformedRectanglesCount = 1;
-    mTransformedRectangles[0] = TransformedRectangle(bounds, transform);
-}
-
-bool RectangleList::intersectWith(const Rect& bounds, const Matrix4& transform) {
-    TransformedRectangle newRectangle(bounds, transform);
-
-    // Try to find a rectangle with a compatible transformation
-    int index = 0;
-    for (; index < mTransformedRectanglesCount; index++) {
-        TransformedRectangle& tr(mTransformedRectangles[index]);
-        if (tr.canSimplyIntersectWith(newRectangle)) {
-            tr.intersectWith(newRectangle);
-            return true;
-        }
-    }
-
-    // Add it to the list if there is room
-    if (index < kMaxTransformedRectangles) {
-        mTransformedRectangles[index] = newRectangle;
-        mTransformedRectanglesCount += 1;
-        return true;
-    }
-
-    // This rectangle list is full
-    return false;
-}
-
-Rect RectangleList::calculateBounds() const {
-    Rect bounds;
-    for (int index = 0; index < mTransformedRectanglesCount; index++) {
-        const TransformedRectangle& tr(mTransformedRectangles[index]);
-        if (index == 0) {
-            bounds = tr.transformedBounds();
-        } else {
-            bounds.doIntersect(tr.transformedBounds());
-        }
-    }
-    return bounds;
-}
-
-static SkPath pathFromTransformedRectangle(const Rect& bounds, const Matrix4& transform) {
-    SkPath rectPath;
-    SkPath rectPathTransformed;
-    rectPath.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom);
-    SkMatrix skTransform;
-    transform.copyTo(skTransform);
-    rectPath.transform(skTransform, &rectPathTransformed);
-    return rectPathTransformed;
-}
-
-SkRegion RectangleList::convertToRegion(const SkRegion& clip) const {
-    SkRegion rectangleListAsRegion;
-    for (int index = 0; index < mTransformedRectanglesCount; index++) {
-        const TransformedRectangle& tr(mTransformedRectangles[index]);
-        SkPath rectPathTransformed =
-                pathFromTransformedRectangle(tr.getBounds(), tr.getTransform());
-        if (index == 0) {
-            rectangleListAsRegion.setPath(rectPathTransformed, clip);
-        } else {
-            SkRegion rectRegion;
-            rectRegion.setPath(rectPathTransformed, clip);
-            rectangleListAsRegion.op(rectRegion, SkRegion::kIntersect_Op);
-        }
-    }
-    return rectangleListAsRegion;
-}
-
-void RectangleList::transform(const Matrix4& transform) {
-    for (int index = 0; index < mTransformedRectanglesCount; index++) {
-        mTransformedRectangles[index].transform(transform);
-    }
-}
-
-/*
- * ClipArea
- */
-
-ClipArea::ClipArea() : mMode(ClipMode::Rectangle) {}
-
-/*
- * Interface
- */
-
-void ClipArea::setViewportDimensions(int width, int height) {
-    mPostViewportClipObserved = false;
-    mViewportBounds.set(0, 0, width, height);
-    mClipRect = mViewportBounds;
-}
-
-void ClipArea::setEmpty() {
-    onClipUpdated();
-    mMode = ClipMode::Rectangle;
-    mClipRect.setEmpty();
-    mClipRegion.setEmpty();
-    mRectangleList.setEmpty();
-}
-
-void ClipArea::setClip(float left, float top, float right, float bottom) {
-    onClipUpdated();
-    mMode = ClipMode::Rectangle;
-    mClipRect.set(left, top, right, bottom);
-    mClipRegion.setEmpty();
-}
-
-void ClipArea::clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op) {
-    if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
-    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
-    onClipUpdated();
-    switch (mMode) {
-        case ClipMode::Rectangle:
-            rectangleModeClipRectWithTransform(r, transform, op);
-            break;
-        case ClipMode::RectangleList:
-            rectangleListModeClipRectWithTransform(r, transform, op);
-            break;
-        case ClipMode::Region:
-            regionModeClipRectWithTransform(r, transform, op);
-            break;
-    }
-}
-
-void ClipArea::clipRegion(const SkRegion& region, SkRegion::Op op) {
-    if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
-    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
-    onClipUpdated();
-    enterRegionMode();
-    mClipRegion.op(region, op);
-    onClipRegionUpdated();
-}
-
-void ClipArea::clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op) {
-    if (op == SkRegion::kReplace_Op) mReplaceOpObserved = true;
-    if (!mPostViewportClipObserved && op == SkRegion::kIntersect_Op) op = SkRegion::kReplace_Op;
-    onClipUpdated();
-    SkMatrix skTransform;
-    transform->copyTo(skTransform);
-    SkPath transformed;
-    path.transform(skTransform, &transformed);
-    SkRegion region;
-    regionFromPath(transformed, region);
-    enterRegionMode();
-    mClipRegion.op(region, op);
-    onClipRegionUpdated();
-}
-
-/*
- * Rectangle mode
- */
-
-void ClipArea::enterRectangleMode() {
-    // Entering rectangle mode discards any
-    // existing clipping information from the other modes.
-    // The only way this occurs is by a clip setting operation.
-    mMode = ClipMode::Rectangle;
-}
-
-void ClipArea::rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform,
-                                                  SkRegion::Op op) {
-    if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
-        mClipRect = r;
-        transform->mapRect(mClipRect);
-        return;
-    } else if (op != SkRegion::kIntersect_Op) {
-        enterRegionMode();
-        regionModeClipRectWithTransform(r, transform, op);
-        return;
-    }
-
-    if (transform->rectToRect()) {
-        Rect transformed(r);
-        transform->mapRect(transformed);
-        mClipRect.doIntersect(transformed);
-        return;
-    }
-
-    enterRectangleListMode();
-    rectangleListModeClipRectWithTransform(r, transform, op);
-}
-
-/*
- * RectangleList mode implementation
- */
-
-void ClipArea::enterRectangleListMode() {
-    // Is is only legal to enter rectangle list mode from
-    // rectangle mode, since rectangle list mode cannot represent
-    // all clip areas that can be represented by a region.
-    ALOG_ASSERT(mMode == ClipMode::Rectangle);
-    mMode = ClipMode::RectangleList;
-    mRectangleList.set(mClipRect, Matrix4::identity());
-}
-
-void ClipArea::rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
-                                                      SkRegion::Op op) {
-    if (op != SkRegion::kIntersect_Op || !mRectangleList.intersectWith(r, *transform)) {
-        enterRegionMode();
-        regionModeClipRectWithTransform(r, transform, op);
-    }
-}
-
-/*
- * Region mode implementation
- */
-
-void ClipArea::enterRegionMode() {
-    ClipMode oldMode = mMode;
-    mMode = ClipMode::Region;
-    if (oldMode != ClipMode::Region) {
-        if (oldMode == ClipMode::Rectangle) {
-            mClipRegion.setRect(mClipRect.toSkIRect());
-        } else {
-            mClipRegion = mRectangleList.convertToRegion(createViewportRegion());
-            onClipRegionUpdated();
-        }
-    }
-}
-
-void ClipArea::regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
-                                               SkRegion::Op op) {
-    SkPath transformedRect = pathFromTransformedRectangle(r, *transform);
-    SkRegion transformedRectRegion;
-    regionFromPath(transformedRect, transformedRectRegion);
-    mClipRegion.op(transformedRectRegion, op);
-    onClipRegionUpdated();
-}
-
-void ClipArea::onClipRegionUpdated() {
-    if (!mClipRegion.isEmpty()) {
-        mClipRect.set(mClipRegion.getBounds());
-
-        if (mClipRegion.isRect()) {
-            mClipRegion.setEmpty();
-            enterRectangleMode();
-        }
-    } else {
-        mClipRect.setEmpty();
-    }
-}
-
-/**
- * Clip serialization
- */
-
-const ClipBase* ClipArea::serializeClip(LinearAllocator& allocator) {
-    if (!mPostViewportClipObserved) {
-        // Only initial clip-to-viewport observed, so no serialization of clip necessary
-        return nullptr;
-    }
-
-    static_assert(std::is_trivially_destructible<Rect>::value,
-                  "expect Rect to be trivially destructible");
-    static_assert(std::is_trivially_destructible<RectangleList>::value,
-                  "expect RectangleList to be trivially destructible");
-
-    if (mLastSerialization == nullptr) {
-        ClipBase* serialization = nullptr;
-        switch (mMode) {
-            case ClipMode::Rectangle:
-                serialization = allocator.create<ClipRect>(mClipRect);
-                break;
-            case ClipMode::RectangleList:
-                serialization = allocator.create<ClipRectList>(mRectangleList);
-                serialization->rect = mRectangleList.calculateBounds();
-                break;
-            case ClipMode::Region:
-                serialization = allocator.create<ClipRegion>(mClipRegion);
-                serialization->rect.set(mClipRegion.getBounds());
-                break;
-        }
-        serialization->intersectWithRoot = mReplaceOpObserved;
-        // TODO: this is only done for draw time, should eventually avoid for record time
-        serialization->rect.snapToPixelBoundaries();
-        mLastSerialization = serialization;
-    }
-    return mLastSerialization;
-}
-
-inline static const RectangleList& getRectList(const ClipBase* scb) {
-    return reinterpret_cast<const ClipRectList*>(scb)->rectList;
-}
-
-inline static const SkRegion& getRegion(const ClipBase* scb) {
-    return reinterpret_cast<const ClipRegion*>(scb)->region;
-}
-
-// Conservative check for too many rectangles to fit in rectangle list.
-// For simplicity, doesn't account for rect merging
-static bool cannotFitInRectangleList(const ClipArea& clipArea, const ClipBase* scb) {
-    int currentRectCount = clipArea.isRectangleList()
-                                   ? clipArea.getRectangleList().getTransformedRectanglesCount()
-                                   : 1;
-    int recordedRectCount = (scb->mode == ClipMode::RectangleList)
-                                    ? getRectList(scb).getTransformedRectanglesCount()
-                                    : 1;
-    return currentRectCount + recordedRectCount > RectangleList::kMaxTransformedRectangles;
-}
-
-static const ClipRect sEmptyClipRect(Rect(0, 0));
-
-const ClipBase* ClipArea::serializeIntersectedClip(LinearAllocator& allocator,
-                                                   const ClipBase* recordedClip,
-                                                   const Matrix4& recordedClipTransform) {
-    // if no recordedClip passed, just serialize current state
-    if (!recordedClip) return serializeClip(allocator);
-
-    // if either is empty, clip is empty
-    if (CC_UNLIKELY(recordedClip->rect.isEmpty()) || mClipRect.isEmpty()) return &sEmptyClipRect;
-
-    if (!mLastResolutionResult || recordedClip != mLastResolutionClip ||
-        recordedClipTransform != mLastResolutionTransform) {
-        mLastResolutionClip = recordedClip;
-        mLastResolutionTransform = recordedClipTransform;
-
-        if (CC_LIKELY(mMode == ClipMode::Rectangle && recordedClip->mode == ClipMode::Rectangle &&
-                      recordedClipTransform.rectToRect())) {
-            // common case - result is a single rectangle
-            auto rectClip = allocator.create<ClipRect>(recordedClip->rect);
-            recordedClipTransform.mapRect(rectClip->rect);
-            rectClip->rect.doIntersect(mClipRect);
-            rectClip->rect.snapToPixelBoundaries();
-            mLastResolutionResult = rectClip;
-        } else if (CC_UNLIKELY(mMode == ClipMode::Region ||
-                               recordedClip->mode == ClipMode::Region ||
-                               cannotFitInRectangleList(*this, recordedClip))) {
-            // region case
-            SkRegion other;
-            switch (recordedClip->mode) {
-                case ClipMode::Rectangle:
-                    if (CC_LIKELY(recordedClipTransform.rectToRect())) {
-                        // simple transform, skip creating SkPath
-                        Rect resultClip(recordedClip->rect);
-                        recordedClipTransform.mapRect(resultClip);
-                        other.setRect(resultClip.toSkIRect());
-                    } else {
-                        SkPath transformedRect = pathFromTransformedRectangle(
-                                recordedClip->rect, recordedClipTransform);
-                        other.setPath(transformedRect, createViewportRegion());
-                    }
-                    break;
-                case ClipMode::RectangleList: {
-                    RectangleList transformedList(getRectList(recordedClip));
-                    transformedList.transform(recordedClipTransform);
-                    other = transformedList.convertToRegion(createViewportRegion());
-                    break;
-                }
-                case ClipMode::Region:
-                    other = getRegion(recordedClip);
-                    applyTransformToRegion(recordedClipTransform, &other);
-            }
-
-            ClipRegion* regionClip = allocator.create<ClipRegion>();
-            switch (mMode) {
-                case ClipMode::Rectangle:
-                    regionClip->region.op(mClipRect.toSkIRect(), other, SkRegion::kIntersect_Op);
-                    break;
-                case ClipMode::RectangleList:
-                    regionClip->region.op(mRectangleList.convertToRegion(createViewportRegion()),
-                                          other, SkRegion::kIntersect_Op);
-                    break;
-                case ClipMode::Region:
-                    regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
-                    break;
-            }
-            // Don't need to snap, since region's in int bounds
-            regionClip->rect.set(regionClip->region.getBounds());
-            mLastResolutionResult = regionClip;
-        } else {
-            auto rectListClip = allocator.create<ClipRectList>(mRectangleList);
-            auto&& rectList = rectListClip->rectList;
-            if (mMode == ClipMode::Rectangle) {
-                rectList.set(mClipRect, Matrix4::identity());
-            }
-
-            if (recordedClip->mode == ClipMode::Rectangle) {
-                rectList.intersectWith(recordedClip->rect, recordedClipTransform);
-            } else {
-                const RectangleList& other = getRectList(recordedClip);
-                for (int i = 0; i < other.getTransformedRectanglesCount(); i++) {
-                    auto&& tr = other.getTransformedRectangle(i);
-                    Matrix4 totalTransform(recordedClipTransform);
-                    totalTransform.multiply(tr.getTransform());
-                    rectList.intersectWith(tr.getBounds(), totalTransform);
-                }
-            }
-            rectListClip->rect = rectList.calculateBounds();
-            rectListClip->rect.snapToPixelBoundaries();
-            mLastResolutionResult = rectListClip;
-        }
-    }
-    return mLastResolutionResult;
-}
-
-void ClipArea::applyClip(const ClipBase* clip, const Matrix4& transform) {
-    if (!clip) return;  // nothing to do
-
-    if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) {
-        clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op);
-    } else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) {
-        auto&& rectList = getRectList(clip);
-        for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) {
-            auto&& tr = rectList.getTransformedRectangle(i);
-            Matrix4 totalTransform(transform);
-            totalTransform.multiply(tr.getTransform());
-            clipRectWithTransform(tr.getBounds(), &totalTransform, SkRegion::kIntersect_Op);
-        }
-    } else {
-        SkRegion region(getRegion(clip));
-        applyTransformToRegion(transform, &region);
-        clipRegion(region, SkRegion::kIntersect_Op);
-    }
-}
-
-void ClipArea::applyTransformToRegion(const Matrix4& transform, SkRegion* region) {
-    if (transform.rectToRect() && !transform.isPureTranslate()) {
-        // handle matrices with scale manually by mapping each rect
-        SkRegion other;
-        SkRegion::Iterator it(*region);
-        while (!it.done()) {
-            Rect rect(it.rect());
-            transform.mapRect(rect);
-            rect.snapGeometryToPixelBoundaries(true);
-            other.op(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kUnion_Op);
-            it.next();
-        }
-        region->swap(other);
-    } else {
-        // TODO: handle non-translate transforms properly!
-        region->translate(transform.getTranslateX(), transform.getTranslateY());
-    }
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
deleted file mode 100644
index a7a1180..0000000
--- a/libs/hwui/ClipArea.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef CLIPAREA_H
-#define CLIPAREA_H
-
-#include "Matrix.h"
-#include "Rect.h"
-#include "utils/Pair.h"
-
-#include <SkRegion.h>
-
-namespace android {
-namespace uirenderer {
-
-class LinearAllocator;
-
-Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
-
-class TransformedRectangle {
-public:
-    TransformedRectangle();
-    TransformedRectangle(const Rect& bounds, const Matrix4& transform);
-
-    bool canSimplyIntersectWith(const TransformedRectangle& other) const;
-    void intersectWith(const TransformedRectangle& other);
-
-    bool isEmpty() const;
-
-    const Rect& getBounds() const { return mBounds; }
-
-    Rect transformedBounds() const {
-        Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
-        return transformedBounds;
-    }
-
-    const Matrix4& getTransform() const { return mTransform; }
-
-    void transform(const Matrix4& transform) {
-        Matrix4 t;
-        t.loadMultiply(transform, mTransform);
-        mTransform = t;
-    }
-
-private:
-    Rect mBounds;
-    Matrix4 mTransform;
-};
-
-class RectangleList {
-public:
-    RectangleList();
-
-    bool isEmpty() const;
-    int getTransformedRectanglesCount() const;
-    const TransformedRectangle& getTransformedRectangle(int i) const;
-
-    void setEmpty();
-    void set(const Rect& bounds, const Matrix4& transform);
-    bool intersectWith(const Rect& bounds, const Matrix4& transform);
-    void transform(const Matrix4& transform);
-
-    SkRegion convertToRegion(const SkRegion& clip) const;
-    Rect calculateBounds() const;
-
-    enum { kMaxTransformedRectangles = 5 };
-
-private:
-    int mTransformedRectanglesCount;
-    TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
-};
-
-enum class ClipMode {
-    Rectangle,
-    RectangleList,
-
-    // region and path - intersected. if either is empty, don't use
-    Region
-};
-
-struct ClipBase {
-    explicit ClipBase(ClipMode mode) : mode(mode) {}
-    explicit ClipBase(const Rect& rect) : mode(ClipMode::Rectangle), rect(rect) {}
-    const ClipMode mode;
-    bool intersectWithRoot = false;
-    // Bounds of the clipping area, used to define the scissor, and define which
-    // portion of the stencil is updated/used
-    Rect rect;
-
-    void dump() const;
-};
-
-struct ClipRect : ClipBase {
-    explicit ClipRect(const Rect& rect) : ClipBase(rect) {}
-};
-
-struct ClipRectList : ClipBase {
-    explicit ClipRectList(const RectangleList& rectList)
-            : ClipBase(ClipMode::RectangleList), rectList(rectList) {}
-    RectangleList rectList;
-};
-
-struct ClipRegion : ClipBase {
-    explicit ClipRegion(const SkRegion& region) : ClipBase(ClipMode::Region), region(region) {}
-    ClipRegion() : ClipBase(ClipMode::Region) {}
-    SkRegion region;
-};
-
-class ClipArea {
-public:
-    ClipArea();
-
-    void setViewportDimensions(int width, int height);
-
-    bool isEmpty() const { return mClipRect.isEmpty(); }
-
-    void setEmpty();
-    void setClip(float left, float top, float right, float bottom);
-    void clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
-    void clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op);
-
-    const Rect& getClipRect() const { return mClipRect; }
-
-    const SkRegion& getClipRegion() const { return mClipRegion; }
-
-    const RectangleList& getRectangleList() const { return mRectangleList; }
-
-    bool isRegion() const { return ClipMode::Region == mMode; }
-
-    bool isSimple() const { return mMode == ClipMode::Rectangle; }
-
-    bool isRectangleList() const { return mMode == ClipMode::RectangleList; }
-
-    WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
-    WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
-            LinearAllocator& allocator, const ClipBase* recordedClip,
-            const Matrix4& recordedClipTransform);
-    void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
-
-    static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
-
-private:
-    void enterRectangleMode();
-    void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
-
-    void enterRectangleListMode();
-    void rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
-                                                SkRegion::Op op);
-
-    void enterRegionModeFromRectangleMode();
-    void enterRegionModeFromRectangleListMode();
-    void enterRegionMode();
-    void regionModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
-
-    void clipRegion(const SkRegion& region, SkRegion::Op op);
-    void ensureClipRegion();
-    void onClipRegionUpdated();
-
-    // Called by every state modifying public method.
-    void onClipUpdated() {
-        mPostViewportClipObserved = true;
-        mLastSerialization = nullptr;
-        mLastResolutionResult = nullptr;
-    }
-
-    SkRegion createViewportRegion() { return SkRegion(mViewportBounds.toSkIRect()); }
-
-    void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
-        // TODO: this should not mask every path to the viewport - this makes it impossible to use
-        // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
-        pathAsRegion.setPath(path, createViewportRegion());
-    }
-
-    ClipMode mMode;
-    bool mPostViewportClipObserved = false;
-    bool mReplaceOpObserved = false;
-
-    /**
-     * If mLastSerialization is non-null, it represents an already serialized copy
-     * of the current clip state. If null, it has not been computed.
-     */
-    const ClipBase* mLastSerialization = nullptr;
-
-    /**
-     * This pair of pointers is a single entry cache of most recently seen
-     */
-    const ClipBase* mLastResolutionResult = nullptr;
-    const ClipBase* mLastResolutionClip = nullptr;
-    Matrix4 mLastResolutionTransform;
-
-    Rect mViewportBounds;
-    Rect mClipRect;
-    SkRegion mClipRegion;
-    RectangleList mRectangleList;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* CLIPAREA_H_ */
diff --git a/libs/hwui/FloatColor.h b/libs/hwui/FloatColor.h
deleted file mode 100644
index b424f97..0000000
--- a/libs/hwui/FloatColor.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef FLOATCOLOR_H
-#define FLOATCOLOR_H
-
-#include "utils/Color.h"
-#include "utils/Macros.h"
-#include "utils/MathUtils.h"
-
-#include <stdint.h>
-
-namespace android {
-namespace uirenderer {
-
-struct FloatColor {
-    // "color" is a gamma-encoded sRGB color
-    // After calling this method, the color is stored as a pre-multiplied linear color
-    // if linear blending is enabled. Otherwise, the color is stored as a pre-multiplied
-    // gamma-encoded sRGB color
-    void set(uint32_t color) {
-        a = ((color >> 24) & 0xff) / 255.0f;
-        r = a * EOCF(((color >> 16) & 0xff) / 255.0f);
-        g = a * EOCF(((color >> 8) & 0xff) / 255.0f);
-        b = a * EOCF(((color)&0xff) / 255.0f);
-    }
-
-    // "color" is a gamma-encoded sRGB color
-    // After calling this method, the color is stored as a un-premultiplied linear color
-    // if linear blending is enabled. Otherwise, the color is stored as a un-premultiplied
-    // gamma-encoded sRGB color
-    void setUnPreMultiplied(uint32_t color) {
-        a = ((color >> 24) & 0xff) / 255.0f;
-        r = EOCF(((color >> 16) & 0xff) / 255.0f);
-        g = EOCF(((color >> 8) & 0xff) / 255.0f);
-        b = EOCF(((color)&0xff) / 255.0f);
-    }
-
-    bool isNotBlack() { return a < 1.0f || r > 0.0f || g > 0.0f || b > 0.0f; }
-
-    bool operator==(const FloatColor& other) const {
-        return MathUtils::areEqual(r, other.r) && MathUtils::areEqual(g, other.g) &&
-               MathUtils::areEqual(b, other.b) && MathUtils::areEqual(a, other.a);
-    }
-
-    bool operator!=(const FloatColor& other) const { return !(*this == other); }
-
-    float r;
-    float g;
-    float b;
-    float a;
-};
-
-REQUIRE_COMPATIBLE_LAYOUT(FloatColor);
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* FLOATCOLOR_H */
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
deleted file mode 100644
index 65bee47..0000000
--- a/libs/hwui/ResourceCache.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2010 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 "ResourceCache.h"
-
-namespace android {
-
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(ResourceCache);
-
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Resource cache
-///////////////////////////////////////////////////////////////////////////////
-
-void ResourceCache::logCache() {
-    ALOGD("ResourceCache: cacheReport:");
-    for (size_t i = 0; i < mCache->size(); ++i) {
-        ResourceReference* ref = mCache->valueAt(i);
-        ALOGD("  ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p", i, mCache->keyAt(i),
-              mCache->valueAt(i));
-        ALOGD("  ResourceCache: mCache(%zu): refCount, destroyed, type = %d, %d, %d", i,
-              ref->refCount, ref->destroyed, ref->resourceType);
-    }
-}
-
-ResourceCache::ResourceCache() {
-    Mutex::Autolock _l(mLock);
-    mCache = new KeyedVector<const void*, ResourceReference*>();
-}
-
-ResourceCache::~ResourceCache() {
-    Mutex::Autolock _l(mLock);
-    delete mCache;
-}
-
-void ResourceCache::lock() {
-    mLock.lock();
-}
-
-void ResourceCache::unlock() {
-    mLock.unlock();
-}
-
-void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
-    Mutex::Autolock _l(mLock);
-    incrementRefcountLocked(resource, resourceType);
-}
-
-void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
-    incrementRefcount((void*)patchResource, kNinePatch);
-}
-
-void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
-    ssize_t index = mCache->indexOfKey(resource);
-    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
-    if (ref == nullptr || mCache->size() == 0) {
-        ref = new ResourceReference(resourceType);
-        mCache->add(resource, ref);
-    }
-    ref->refCount++;
-}
-
-void ResourceCache::decrementRefcount(void* resource) {
-    Mutex::Autolock _l(mLock);
-    decrementRefcountLocked(resource);
-}
-
-void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
-    decrementRefcount((void*)patchResource);
-}
-
-void ResourceCache::decrementRefcountLocked(void* resource) {
-    ssize_t index = mCache->indexOfKey(resource);
-    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
-    if (ref == nullptr) {
-        // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
-        return;
-    }
-    ref->refCount--;
-    if (ref->refCount == 0) {
-        deleteResourceReferenceLocked(resource, ref);
-    }
-}
-
-void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
-    decrementRefcountLocked((void*)patchResource);
-}
-
-void ResourceCache::destructor(Res_png_9patch* resource) {
-    Mutex::Autolock _l(mLock);
-    destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(Res_png_9patch* resource) {
-    ssize_t index = mCache->indexOfKey(resource);
-    ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : nullptr;
-    if (ref == nullptr) {
-        // If we're not tracking this resource, just delete it
-        // A Res_png_9patch is actually an array of byte that's larger
-        // than sizeof(Res_png_9patch). It must be freed as an array.
-        delete[](int8_t*) resource;
-        return;
-    }
-    ref->destroyed = true;
-    if (ref->refCount == 0) {
-        deleteResourceReferenceLocked(resource, ref);
-    }
-}
-
-/**
- * This method should only be called while the mLock mutex is held (that mutex is grabbed
- * by the various destructor() and recycle() methods which call this method).
- */
-void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) {
-    if (ref->destroyed) {
-        switch (ref->resourceType) {
-            case kNinePatch: {
-                // A Res_png_9patch is actually an array of byte that's larger
-                // than sizeof(Res_png_9patch). It must be freed as an array.
-                int8_t* patch = (int8_t*)resource;
-                delete[] patch;
-            } break;
-        }
-    }
-    mCache->removeItem(resource);
-    delete ref;
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
deleted file mode 100644
index fd3f9fd..0000000
--- a/libs/hwui/ResourceCache.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef ANDROID_HWUI_RESOURCE_CACHE_H
-#define ANDROID_HWUI_RESOURCE_CACHE_H
-
-#include <cutils/compiler.h>
-
-#include <SkBitmap.h>
-#include <SkPixelRef.h>
-
-#include <utils/KeyedVector.h>
-#include <utils/Singleton.h>
-
-#include <androidfw/ResourceTypes.h>
-
-namespace android {
-namespace uirenderer {
-
-class Layer;
-
-/**
- * Type of Resource being cached
- */
-enum ResourceType {
-    kNinePatch,
-};
-
-class ResourceReference {
-public:
-    explicit ResourceReference(ResourceType type) {
-        refCount = 0;
-        destroyed = false;
-        resourceType = type;
-    }
-
-    int refCount;
-    bool destroyed;
-    ResourceType resourceType;
-};
-
-class ANDROID_API ResourceCache : public Singleton<ResourceCache> {
-    ResourceCache();
-    ~ResourceCache();
-
-    friend class Singleton<ResourceCache>;
-
-public:
-    /**
-     * When using these two methods, make sure to only invoke the *Locked()
-     * variants of increment/decrementRefcount(), recyle() and destructor()
-     */
-    void lock();
-    void unlock();
-
-    void incrementRefcount(const Res_png_9patch* resource);
-
-    void decrementRefcount(const Res_png_9patch* resource);
-
-    void decrementRefcountLocked(const Res_png_9patch* resource);
-
-    void destructor(Res_png_9patch* resource);
-
-    void destructorLocked(Res_png_9patch* resource);
-
-private:
-    void deleteResourceReferenceLocked(const void* resource, ResourceReference* ref);
-
-    void incrementRefcount(void* resource, ResourceType resourceType);
-    void incrementRefcountLocked(void* resource, ResourceType resourceType);
-
-    void decrementRefcount(void* resource);
-    void decrementRefcountLocked(void* resource);
-
-    void logCache();
-
-    /**
-     * Used to increment, decrement, and destroy. Incrementing is generally accessed on the UI
-     * thread, but destroying resources may be called from the GC thread, the finalizer thread,
-     * or a reference queue finalization thread.
-     */
-    mutable Mutex mLock;
-
-    KeyedVector<const void*, ResourceReference*>* mCache;
-};
-
-};  // namespace uirenderer
-};  // namespace android
-
-#endif  // ANDROID_HWUI_RESOURCE_CACHE_H
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
deleted file mode 100644
index f1a1bef..0000000
--- a/libs/hwui/Snapshot.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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.
- */
-
-#include "Snapshot.h"
-
-#include "hwui/Canvas.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Constructors
-///////////////////////////////////////////////////////////////////////////////
-
-Snapshot::Snapshot()
-        : flags(0)
-        , previous(nullptr)
-        , layer(nullptr)
-        , fbo(0)
-        , alpha(1.0f)
-        , roundRectClipState(nullptr)
-        , projectionPathMask(nullptr)
-        , mClipArea(&mClipAreaRoot) {
-    transform = &mTransformRoot;
-    mRelativeLightCenter.x = mRelativeLightCenter.y = mRelativeLightCenter.z = 0;
-}
-
-/**
- * Copies the specified snapshot/ The specified snapshot is stored as
- * the previous snapshot.
- */
-Snapshot::Snapshot(Snapshot* s, int saveFlags)
-        : flags(0)
-        , previous(s)
-        , layer(s->layer)
-        , fbo(s->fbo)
-        , alpha(s->alpha)
-        , roundRectClipState(s->roundRectClipState)
-        , projectionPathMask(s->projectionPathMask)
-        , mClipArea(nullptr)
-        , mViewportData(s->mViewportData)
-        , mRelativeLightCenter(s->mRelativeLightCenter) {
-    if (saveFlags & SaveFlags::Matrix) {
-        mTransformRoot = *s->transform;
-        transform = &mTransformRoot;
-    } else {
-        transform = s->transform;
-    }
-
-    if (saveFlags & SaveFlags::Clip) {
-        mClipAreaRoot = s->getClipArea();
-        mClipArea = &mClipAreaRoot;
-    } else {
-        mClipArea = s->mClipArea;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Clipping
-///////////////////////////////////////////////////////////////////////////////
-
-void Snapshot::clip(const Rect& localClip, SkClipOp op) {
-    flags |= Snapshot::kFlagClipSet;
-    mClipArea->clipRectWithTransform(localClip, transform, static_cast<SkRegion::Op>(op));
-}
-
-void Snapshot::clipPath(const SkPath& path, SkClipOp op) {
-    flags |= Snapshot::kFlagClipSet;
-    mClipArea->clipPathWithTransform(path, transform, static_cast<SkRegion::Op>(op));
-}
-
-void Snapshot::setClip(float left, float top, float right, float bottom) {
-    flags |= Snapshot::kFlagClipSet;
-    mClipArea->setClip(left, top, right, bottom);
-}
-
-bool Snapshot::hasPerspectiveTransform() const {
-    return transform->isPerspective();
-}
-
-const Rect& Snapshot::getLocalClip() {
-    mat4 inverse;
-    inverse.loadInverse(*transform);
-
-    mLocalClip.set(mClipArea->getClipRect());
-    inverse.mapRect(mLocalClip);
-
-    return mLocalClip;
-}
-
-void Snapshot::resetClip(float left, float top, float right, float bottom) {
-    // TODO: This is incorrect, when we start rendering into a new layer,
-    // we may have to modify the previous snapshot's clip rect and clip
-    // region if the previous restore() call did not restore the clip
-    mClipArea = &mClipAreaRoot;
-    setClip(left, top, right, bottom);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Clipping round rect
-///////////////////////////////////////////////////////////////////////////////
-
-void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius,
-                                    bool highPriority) {
-    if (bounds.isEmpty()) {
-        mClipArea->setEmpty();
-        return;
-    }
-
-    if (roundRectClipState && roundRectClipState->highPriority) {
-        // ignore, don't replace, already have a high priority clip
-        return;
-    }
-
-    RoundRectClipState* state = new (allocator) RoundRectClipState;
-
-    state->highPriority = highPriority;
-
-    // store the inverse drawing matrix
-    Matrix4 roundRectDrawingMatrix = getOrthoMatrix();
-    roundRectDrawingMatrix.multiply(*transform);
-    state->matrix.loadInverse(roundRectDrawingMatrix);
-
-    // compute area under rounded corners - only draws overlapping these rects need to be clipped
-    for (int i = 0; i < 4; i++) {
-        state->dangerRects[i] = bounds;
-    }
-    state->dangerRects[0].bottom = state->dangerRects[1].bottom = bounds.top + radius;
-    state->dangerRects[0].right = state->dangerRects[2].right = bounds.left + radius;
-    state->dangerRects[1].left = state->dangerRects[3].left = bounds.right - radius;
-    state->dangerRects[2].top = state->dangerRects[3].top = bounds.bottom - radius;
-    for (int i = 0; i < 4; i++) {
-        transform->mapRect(state->dangerRects[i]);
-
-        // round danger rects out as though they are AA geometry (since they essentially are)
-        state->dangerRects[i].snapGeometryToPixelBoundaries(true);
-    }
-
-    // store RR area
-    state->innerRect = bounds;
-    state->innerRect.inset(radius);
-    state->radius = radius;
-
-    // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info
-    roundRectClipState = state;
-}
-
-void Snapshot::setProjectionPathMask(const SkPath* path) {
-    projectionPathMask = path;
-}
-
-static Snapshot* getClipRoot(Snapshot* target) {
-    while (target->previous && target->previous->previous) {
-        target = target->previous;
-    }
-    return target;
-}
-
-const ClipBase* Snapshot::serializeIntersectedClip(LinearAllocator& allocator,
-                                                   const ClipBase* recordedClip,
-                                                   const Matrix4& recordedClipTransform) {
-    auto target = this;
-    if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
-        // Clip must be intersected with root, instead of current clip.
-        target = getClipRoot(this);
-    }
-
-    return target->mClipArea->serializeIntersectedClip(allocator, recordedClip,
-                                                       recordedClipTransform);
-}
-
-void Snapshot::applyClip(const ClipBase* recordedClip, const Matrix4& transform) {
-    if (CC_UNLIKELY(recordedClip && recordedClip->intersectWithRoot)) {
-        // current clip is being replaced, but must intersect with clip root
-        *mClipArea = *(getClipRoot(this)->mClipArea);
-    }
-    mClipArea->applyClip(recordedClip, transform);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Queries
-///////////////////////////////////////////////////////////////////////////////
-
-void Snapshot::dump() const {
-    ALOGD("Snapshot %p, flags %x, prev %p, height %d, hasComplexClip %d", this, flags, previous,
-          getViewportHeight(), !mClipArea->isSimple());
-    const Rect& clipRect(mClipArea->getClipRect());
-    ALOGD("  ClipRect %.1f %.1f %.1f %.1f, clip simple %d", clipRect.left, clipRect.top,
-          clipRect.right, clipRect.bottom, mClipArea->isSimple());
-
-    ALOGD("  Transform (at %p):", transform);
-    transform->dump();
-}
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
deleted file mode 100644
index 655f819..0000000
--- a/libs/hwui/Snapshot.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <ui/Region.h>
-#include <utils/LinearAllocator.h>
-#include <utils/RefBase.h>
-
-#include <SkClipOp.h>
-#include <SkRegion.h>
-
-#include "ClipArea.h"
-#include "Layer.h"
-#include "Matrix.h"
-#include "Outline.h"
-#include "Rect.h"
-#include "utils/Macros.h"
-
-namespace android {
-namespace uirenderer {
-
-/**
- * Temporary structure holding information for a single outline clip.
- *
- * These structures are treated as immutable once created, and only exist for a single frame, which
- * is why they may only be allocated with a LinearAllocator.
- */
-class RoundRectClipState {
-public:
-    static void* operator new(size_t size) = delete;
-    static void* operator new(size_t size, LinearAllocator& allocator) {
-        return allocator.alloc<RoundRectClipState>(size);
-    }
-
-    bool areaRequiresRoundRectClip(const Rect& rect) const {
-        return rect.intersects(dangerRects[0]) || rect.intersects(dangerRects[1]) ||
-               rect.intersects(dangerRects[2]) || rect.intersects(dangerRects[3]);
-    }
-
-    bool highPriority;
-    Matrix4 matrix;
-    Rect dangerRects[4];
-    Rect innerRect;
-    float radius;
-};
-
-/**
- * A snapshot holds information about the current state of the rendering
- * surface. A snapshot is usually created whenever the user calls save()
- * and discarded when the user calls restore(). Once a snapshot is created,
- * it can hold information for deferred rendering.
- *
- * Each snapshot has a link to a previous snapshot, indicating the previous
- * state of the renderer.
- */
-class Snapshot {
-public:
-    Snapshot();
-    Snapshot(Snapshot* s, int saveFlags);
-
-    /**
-     * Various flags set on ::flags.
-     */
-    enum Flags {
-        /**
-         * Indicates that the clip region was modified. When this
-         * snapshot is restored so must the clip.
-         */
-        kFlagClipSet = 0x1,
-        /**
-         * Indicates that this snapshot was created when saving
-         * a new layer.
-         */
-        kFlagIsLayer = 0x2,
-        /**
-         * Indicates that this snapshot is a special type of layer
-         * backed by an FBO. This flag only makes sense when the
-         * flag kFlagIsLayer is also set.
-         *
-         * Viewport has been modified to fit the new Fbo, and must be
-         * restored when this snapshot is restored.
-         */
-        kFlagIsFboLayer = 0x4,
-    };
-
-    /**
-     * Modifies the current clip with the new clip rectangle and
-     * the specified operation. The specified rectangle is transformed
-     * by this snapshot's trasnformation.
-     */
-    void clip(const Rect& localClip, SkClipOp op);
-
-    /**
-     * Modifies the current clip with the new clip rectangle and
-     * the specified operation. The specified rectangle is considered
-     * already transformed.
-     */
-    void clipTransformed(const Rect& r, SkClipOp op = SkClipOp::kIntersect);
-
-    /**
-     * Modifies the current clip with the specified path and operation.
-     */
-    void clipPath(const SkPath& path, SkClipOp op);
-
-    /**
-     * Sets the current clip.
-     */
-    void setClip(float left, float top, float right, float bottom);
-
-    /**
-     * Returns the current clip in local coordinates. The clip rect is
-     * transformed by the inverse transform matrix.
-     */
-    ANDROID_API const Rect& getLocalClip();
-
-    /**
-     * Returns the current clip in render target coordinates.
-     */
-    const Rect& getRenderTargetClip() const { return mClipArea->getClipRect(); }
-
-    /*
-     * Accessor functions so that the clip area can stay private
-     */
-    bool clipIsEmpty() const { return mClipArea->isEmpty(); }
-    const SkRegion& getClipRegion() const { return mClipArea->getClipRegion(); }
-    bool clipIsSimple() const { return mClipArea->isSimple(); }
-    const ClipArea& getClipArea() const { return *mClipArea; }
-    ClipArea& mutateClipArea() { return *mClipArea; }
-
-    WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
-            LinearAllocator& allocator, const ClipBase* recordedClip,
-            const Matrix4& recordedClipTransform);
-    void applyClip(const ClipBase* clip, const Matrix4& transform);
-
-    /**
-     * Resets the clip to the specified rect.
-     */
-    void resetClip(float left, float top, float right, float bottom);
-
-    void initializeViewport(int width, int height) {
-        mViewportData.initialize(width, height);
-        mClipAreaRoot.setViewportDimensions(width, height);
-    }
-
-    int getViewportWidth() const { return mViewportData.mWidth; }
-    int getViewportHeight() const { return mViewportData.mHeight; }
-    const Matrix4& getOrthoMatrix() const { return mViewportData.mOrthoMatrix; }
-
-    const Vector3& getRelativeLightCenter() const { return mRelativeLightCenter; }
-    void setRelativeLightCenter(const Vector3& lightCenter) { mRelativeLightCenter = lightCenter; }
-
-    /**
-     * Sets (and replaces) the current clipping outline
-     *
-     * If the current round rect clip is high priority, the incoming clip is ignored.
-     */
-    void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius,
-                              bool highPriority);
-
-    /**
-     * Sets (and replaces) the current projection mask
-     */
-    void setProjectionPathMask(const SkPath* path);
-
-    /**
-     * Indicates whether the current transform has perspective components.
-     */
-    bool hasPerspectiveTransform() const;
-
-    /**
-     * Dirty flags.
-     */
-    int flags;
-
-    /**
-     * Previous snapshot.
-     */
-    Snapshot* previous;
-
-    /**
-     * A pointer to the currently active layer.
-     *
-     * This snapshot does not own the layer, this pointer must not be freed.
-     */
-    Layer* layer;
-
-    /**
-     * Target FBO used for rendering. Set to 0 when rendering directly
-     * into the framebuffer.
-     */
-    GLuint fbo;
-
-    /**
-     * Local transformation. Holds the current translation, scale and
-     * rotation values.
-     *
-     * This is a reference to a matrix owned by this snapshot or another
-     *  snapshot. This pointer must not be freed. See ::mTransformRoot.
-     */
-    mat4* transform;
-
-    /**
-     * Current alpha value. This value is 1 by default, but may be set by a DisplayList which
-     * has translucent rendering in a non-overlapping View. This value will be used by
-     * the renderer to set the alpha in the current color being used for ensuing drawing
-     * operations. The value is inherited by child snapshots because the same value should
-     * be applied to descendants of the current DisplayList (for example, a TextView contains
-     * the base alpha value which should be applied to the child DisplayLists used for drawing
-     * the actual text).
-     */
-    float alpha;
-
-    /**
-     * Current clipping round rect.
-     *
-     * Points to data not owned by the snapshot, and may only be replaced by subsequent RR clips,
-     * never modified.
-     */
-    const RoundRectClipState* roundRectClipState;
-
-    /**
-     * Current projection masking path - used exclusively to mask projected, tessellated circles.
-     */
-    const SkPath* projectionPathMask;
-
-    void dump() const;
-
-private:
-    struct ViewportData {
-        ViewportData() : mWidth(0), mHeight(0) {}
-        void initialize(int width, int height) {
-            mWidth = width;
-            mHeight = height;
-            mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
-        }
-
-        /*
-         * Width and height of current viewport.
-         *
-         * The viewport is always defined to be (0, 0, width, height).
-         */
-        int mWidth;
-        int mHeight;
-        /**
-         * Contains the current orthographic, projection matrix.
-         */
-        mat4 mOrthoMatrix;
-    };
-
-    mat4 mTransformRoot;
-
-    ClipArea mClipAreaRoot;
-    ClipArea* mClipArea;
-    Rect mLocalClip;
-
-    ViewportData mViewportData;
-    Vector3 mRelativeLightCenter;
-
-};  // class Snapshot
-
-};  // namespace uirenderer
-};  // namespace android
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index a6aae55..f091277 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -19,7 +19,6 @@
 
 #include "Vector.h"
 
-#include "FloatColor.h"
 #include "utils/Macros.h"
 
 namespace android {
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index a00b8db..c5db861d 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -21,7 +21,6 @@
 #include <Properties.h>
 #include <Rect.h>
 #include <RenderNode.h>
-#include <Snapshot.h>
 #include <hwui/Bitmap.h>
 #include <pipeline/skia/SkiaRecordingCanvas.h>
 #include <private/hwui/DrawGlInfo.h>
@@ -141,14 +140,6 @@
         return true;
     }
 
-    static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
-        std::unique_ptr<Snapshot> snapshot(new Snapshot());
-        // store clip first, so it isn't transformed
-        snapshot->setClip(clip.left, clip.top, clip.right, clip.bottom);
-        *(snapshot->transform) = transform;
-        return snapshot;
-    }
-
     static sk_sp<Bitmap> createBitmap(int width, int height,
                                       SkColorType colorType = kN32_SkColorType) {
         SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 9388c20..70423a7 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -16,7 +16,6 @@
 
 #include <benchmark/benchmark.h>
 
-#include "CanvasState.h"
 #include "DisplayList.h"
 #include "hwui/Canvas.h"
 #include "pipeline/skia/SkiaDisplayList.h"
@@ -116,52 +115,6 @@
 }
 BENCHMARK(BM_DisplayListCanvas_record_simpleBitmapView);
 
-class NullClient : public CanvasStateClient {
-    void onViewportInitialized() override {}
-    void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
-    GLuint getTargetFbo() const override { return 0; }
-};
-
-void BM_CanvasState_saverestore(benchmark::State& benchState) {
-    NullClient client;
-    CanvasState state(client);
-    state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
-
-    while (benchState.KeepRunning()) {
-        state.save(SaveFlags::MatrixClip);
-        state.save(SaveFlags::MatrixClip);
-        benchmark::DoNotOptimize(&state);
-        state.restore();
-        state.restore();
-    }
-}
-BENCHMARK(BM_CanvasState_saverestore);
-
-void BM_CanvasState_init(benchmark::State& benchState) {
-    NullClient client;
-    CanvasState state(client);
-    state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
-
-    while (benchState.KeepRunning()) {
-        state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
-        benchmark::DoNotOptimize(&state);
-    }
-}
-BENCHMARK(BM_CanvasState_init);
-
-void BM_CanvasState_translate(benchmark::State& benchState) {
-    NullClient client;
-    CanvasState state(client);
-    state.initializeSaveStack(100, 100, 0, 0, 100, 100, Vector3());
-
-    while (benchState.KeepRunning()) {
-        state.translate(5, 5, 0);
-        benchmark::DoNotOptimize(&state);
-        state.translate(-5, -5, 0);
-    }
-}
-BENCHMARK(BM_CanvasState_translate);
-
 void BM_DisplayListCanvas_basicViewGroupDraw(benchmark::State& benchState) {
     sp<RenderNode> child = TestUtils::createNode(50, 50, 100, 100, [](auto& props, auto& canvas) {
         canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver);
diff --git a/libs/hwui/tests/unit/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
deleted file mode 100644
index 4c03811..0000000
--- a/libs/hwui/tests/unit/CanvasStateTests.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2015 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 "CanvasState.h"
-
-#include "Matrix.h"
-#include "Rect.h"
-#include "hwui/Canvas.h"
-#include "utils/LinearAllocator.h"
-
-#include <SkClipOp.h>
-#include <SkPath.h>
-#include <gtest/gtest.h>
-
-namespace android {
-namespace uirenderer {
-
-class NullClient : public CanvasStateClient {
-    void onViewportInitialized() override {}
-    void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
-    GLuint getTargetFbo() const override { return 0; }
-};
-
-static NullClient sNullClient;
-
-static bool approxEqual(const Matrix4& a, const Matrix4& b) {
-    for (int i = 0; i < 16; i++) {
-        if (!MathUtils::areEqual(a[i], b[i])) {
-            return false;
-        }
-    }
-    return true;
-}
-
-TEST(CanvasState, gettersAndSetters) {
-    CanvasState state(sNullClient);
-    state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
-
-    ASSERT_EQ(state.getWidth(), 200);
-    ASSERT_EQ(state.getHeight(), 200);
-
-    Matrix4 simpleTranslate;
-    simpleTranslate.loadTranslate(10, 20, 0);
-    state.setMatrix(simpleTranslate);
-
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200));
-    ASSERT_EQ(state.getLocalClipBounds(), Rect(-10, -20, 190, 180));
-    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
-    EXPECT_TRUE(state.clipIsSimple());
-}
-
-TEST(CanvasState, simpleClipping) {
-    CanvasState state(sNullClient);
-    state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
-
-    state.clipRect(0, 0, 100, 100, SkClipOp::kIntersect);
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(100, 100));
-
-    state.clipRect(10, 10, 200, 200, SkClipOp::kIntersect);
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10, 100, 100));
-
-    state.clipRect(50, 50, 150, 150, SkClipOp::kReplace_deprecated);
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(50, 50, 150, 150));
-}
-
-TEST(CanvasState, complexClipping) {
-    CanvasState state(sNullClient);
-    state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
-
-    state.save(SaveFlags::MatrixClip);
-    {
-        // rotated clip causes complex clip
-        state.rotate(10);
-        EXPECT_TRUE(state.clipIsSimple());
-        state.clipRect(0, 0, 200, 200, SkClipOp::kIntersect);
-        EXPECT_FALSE(state.clipIsSimple());
-    }
-    state.restore();
-
-    state.save(SaveFlags::MatrixClip);
-    {
-        // subtracted clip causes complex clip
-        EXPECT_TRUE(state.clipIsSimple());
-        state.clipRect(50, 50, 150, 150, SkClipOp::kDifference);
-        EXPECT_FALSE(state.clipIsSimple());
-    }
-    state.restore();
-
-    state.save(SaveFlags::MatrixClip);
-    {
-        // complex path causes complex clip
-        SkPath path;
-        path.addOval(SkRect::MakeWH(200, 200));
-        EXPECT_TRUE(state.clipIsSimple());
-        state.clipPath(&path, SkClipOp::kDifference);
-        EXPECT_FALSE(state.clipIsSimple());
-    }
-    state.restore();
-}
-
-TEST(CanvasState, saveAndRestore) {
-    CanvasState state(sNullClient);
-    state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
-
-    state.save(SaveFlags::Clip);
-    {
-        state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
-        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
-    }
-    state.restore();
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(200, 200));  // verify restore
-
-    Matrix4 simpleTranslate;
-    simpleTranslate.loadTranslate(10, 10, 0);
-    state.save(SaveFlags::Matrix);
-    {
-        state.translate(10, 10, 0);
-        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
-    }
-    state.restore();
-    EXPECT_FALSE(approxEqual(*state.currentTransform(), simpleTranslate));
-}
-
-TEST(CanvasState, saveAndRestoreButNotTooMuch) {
-    CanvasState state(sNullClient);
-    state.initializeSaveStack(200, 200, 0, 0, 200, 200, Vector3());
-
-    state.save(SaveFlags::Matrix);  // NOTE: clip not saved
-    {
-        state.clipRect(0, 0, 10, 10, SkClipOp::kIntersect);
-        ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));
-    }
-    state.restore();
-    ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(10, 10));  // verify not restored
-
-    Matrix4 simpleTranslate;
-    simpleTranslate.loadTranslate(10, 10, 0);
-    state.save(SaveFlags::Clip);  // NOTE: matrix not saved
-    {
-        state.translate(10, 10, 0);
-        EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));
-    }
-    state.restore();
-    EXPECT_TRUE(approxEqual(*state.currentTransform(), simpleTranslate));  // verify not restored
-}
-}
-}
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
deleted file mode 100644
index 450bb67..0000000
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (C) 2015 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 <SkPath.h>
-#include <SkRegion.h>
-#include <gtest/gtest.h>
-
-#include "ClipArea.h"
-
-#include "Matrix.h"
-#include "Rect.h"
-#include "utils/LinearAllocator.h"
-
-namespace android {
-namespace uirenderer {
-
-static Rect kViewportBounds(2048, 2048);
-
-static ClipArea createClipArea() {
-    ClipArea area;
-    area.setViewportDimensions(kViewportBounds.getWidth(), kViewportBounds.getHeight());
-    return area;
-}
-
-TEST(TransformedRectangle, basics) {
-    Rect r(0, 0, 100, 100);
-    Matrix4 minus90;
-    minus90.loadRotate(-90);
-    minus90.mapRect(r);
-    Rect r2(20, 40, 120, 60);
-
-    Matrix4 m90;
-    m90.loadRotate(90);
-    TransformedRectangle tr(r, m90);
-    EXPECT_TRUE(tr.canSimplyIntersectWith(tr));
-
-    Matrix4 m0;
-    TransformedRectangle tr0(r2, m0);
-    EXPECT_FALSE(tr.canSimplyIntersectWith(tr0));
-
-    Matrix4 m45;
-    m45.loadRotate(45);
-    TransformedRectangle tr2(r, m45);
-    EXPECT_FALSE(tr2.canSimplyIntersectWith(tr));
-}
-
-TEST(RectangleList, basics) {
-    RectangleList list;
-    EXPECT_TRUE(list.isEmpty());
-
-    Rect r(0, 0, 100, 100);
-    Matrix4 m45;
-    m45.loadRotate(45);
-    list.set(r, m45);
-    EXPECT_FALSE(list.isEmpty());
-
-    Rect r2(20, 20, 200, 200);
-    list.intersectWith(r2, m45);
-    EXPECT_FALSE(list.isEmpty());
-    EXPECT_EQ(1, list.getTransformedRectanglesCount());
-
-    Rect r3(20, 20, 200, 200);
-    Matrix4 m30;
-    m30.loadRotate(30);
-    list.intersectWith(r2, m30);
-    EXPECT_FALSE(list.isEmpty());
-    EXPECT_EQ(2, list.getTransformedRectanglesCount());
-
-    SkRegion clip;
-    clip.setRect(0, 0, 2000, 2000);
-    SkRegion rgn(list.convertToRegion(clip));
-    EXPECT_FALSE(rgn.isEmpty());
-}
-
-TEST(ClipArea, basics) {
-    ClipArea area(createClipArea());
-    EXPECT_FALSE(area.isEmpty());
-}
-
-TEST(ClipArea, paths) {
-    ClipArea area(createClipArea());
-    SkPath path;
-    SkScalar r = 100;
-    path.addCircle(r, r, r);
-    area.clipPathWithTransform(path, &Matrix4::identity(), SkRegion::kIntersect_Op);
-    EXPECT_FALSE(area.isEmpty());
-    EXPECT_FALSE(area.isSimple());
-    EXPECT_FALSE(area.isRectangleList());
-
-    Rect clipRect(area.getClipRect());
-    Rect expected(0, 0, r * 2, r * 2);
-    EXPECT_EQ(expected, clipRect);
-    SkRegion clipRegion(area.getClipRegion());
-    auto skRect(clipRegion.getBounds());
-    Rect regionBounds;
-    regionBounds.set(skRect);
-    EXPECT_EQ(expected, regionBounds);
-}
-
-TEST(ClipArea, replaceNegative) {
-    ClipArea area(createClipArea());
-    area.setClip(0, 0, 100, 100);
-
-    Rect expected(-50, -50, 50, 50);
-    area.clipRectWithTransform(expected, &Matrix4::identity(), SkRegion::kReplace_Op);
-    EXPECT_EQ(expected, area.getClipRect());
-}
-
-TEST(ClipArea, serializeClip) {
-    ClipArea area(createClipArea());
-    LinearAllocator allocator;
-
-    // unset clip
-    EXPECT_EQ(nullptr, area.serializeClip(allocator));
-
-    // rect clip
-    area.setClip(0, 0, 200, 200);
-    {
-        auto serializedClip = area.serializeClip(allocator);
-        ASSERT_NE(nullptr, serializedClip);
-        ASSERT_EQ(ClipMode::Rectangle, serializedClip->mode);
-        ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
-        EXPECT_EQ(Rect(200, 200), serializedClip->rect);
-        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
-                << "Requery of clip on unmodified ClipArea must return same pointer.";
-    }
-
-    // rect list
-    Matrix4 rotate;
-    rotate.loadRotate(5.0f);
-    area.clipRectWithTransform(Rect(50, 50, 150, 150), &rotate, SkRegion::kIntersect_Op);
-    {
-        auto serializedClip = area.serializeClip(allocator);
-        ASSERT_NE(nullptr, serializedClip);
-        ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
-        ASSERT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
-        auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
-        EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
-        EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
-        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
-                << "Requery of clip on unmodified ClipArea must return same pointer.";
-    }
-
-    // region
-    SkPath circlePath;
-    circlePath.addCircle(100, 100, 100);
-    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kReplace_Op);
-    {
-        auto serializedClip = area.serializeClip(allocator);
-        ASSERT_NE(nullptr, serializedClip);
-        ASSERT_EQ(ClipMode::Region, serializedClip->mode);
-        ASSERT_TRUE(serializedClip->intersectWithRoot) << "Replace op, so expect intersectWithRoot";
-        auto clipRegion = reinterpret_cast<const ClipRegion*>(serializedClip);
-        EXPECT_EQ(SkIRect::MakeWH(200, 200), clipRegion->region.getBounds())
-                << "Clip region should be 200x200";
-        EXPECT_EQ(Rect(200, 200), clipRegion->rect);
-        EXPECT_EQ(serializedClip, area.serializeClip(allocator))
-                << "Requery of clip on unmodified ClipArea must return same pointer.";
-    }
-}
-
-TEST(ClipArea, serializeClip_pathIntersectWithRoot) {
-    ClipArea area(createClipArea());
-    LinearAllocator allocator;
-    SkPath circlePath;
-    circlePath.addCircle(100, 100, 100);
-    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kIntersect_Op);
-
-    auto serializedClip = area.serializeClip(allocator);
-    ASSERT_NE(nullptr, serializedClip);
-    EXPECT_FALSE(serializedClip->intersectWithRoot) << "No replace, so no intersectWithRoot";
-}
-
-TEST(ClipArea, serializeIntersectedClip) {
-    ClipArea area(createClipArea());
-    LinearAllocator allocator;
-
-    // simple state;
-    EXPECT_EQ(nullptr, area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
-    area.setClip(0, 0, 200, 200);
-    {
-        auto origRectClip = area.serializeClip(allocator);
-        ASSERT_NE(nullptr, origRectClip);
-        EXPECT_EQ(origRectClip,
-                  area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity()));
-    }
-
-    // rect
-    {
-        ClipRect recordedClip(Rect(100, 100));
-        Matrix4 translateScale;
-        translateScale.loadTranslate(100, 100, 0);
-        translateScale.scale(2, 3, 1);
-        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
-        ASSERT_NE(nullptr, resolvedClip);
-        ASSERT_EQ(ClipMode::Rectangle, resolvedClip->mode);
-        EXPECT_EQ(Rect(100, 100, 200, 200), resolvedClip->rect);
-
-        EXPECT_EQ(resolvedClip,
-                  area.serializeIntersectedClip(allocator, &recordedClip, translateScale))
-                << "Must return previous serialization, since input is same";
-
-        ClipRect recordedClip2(Rect(100, 100));
-        EXPECT_NE(resolvedClip,
-                  area.serializeIntersectedClip(allocator, &recordedClip2, translateScale))
-                << "Shouldn't return previous serialization, since matrix location is different";
-    }
-
-    // rect list
-    Matrix4 rotate;
-    rotate.loadRotate(2.0f);
-    area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
-    {
-        ClipRect recordedClip(Rect(100, 100));
-        auto resolvedClip =
-                area.serializeIntersectedClip(allocator, &recordedClip, Matrix4::identity());
-        ASSERT_NE(nullptr, resolvedClip);
-        ASSERT_EQ(ClipMode::RectangleList, resolvedClip->mode);
-        auto clipRectList = reinterpret_cast<const ClipRectList*>(resolvedClip);
-        EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
-    }
-
-    // region
-    SkPath circlePath;
-    circlePath.addCircle(100, 100, 100);
-    area.clipPathWithTransform(circlePath, &Matrix4::identity(), SkRegion::kReplace_Op);
-    {
-        SkPath ovalPath;
-        ovalPath.addOval(SkRect::MakeLTRB(50, 0, 150, 200));
-
-        ClipRegion recordedClip;
-        recordedClip.region.setPath(ovalPath, SkRegion(SkIRect::MakeWH(200, 200)));
-        recordedClip.rect = Rect(200, 200);
-
-        Matrix4 translate10x20;
-        translate10x20.loadTranslate(10, 20, 0);
-        auto resolvedClip = area.serializeIntersectedClip(
-                allocator, &recordedClip,
-                translate10x20);  // Note: only translate for now, others not handled correctly
-        ASSERT_NE(nullptr, resolvedClip);
-        ASSERT_EQ(ClipMode::Region, resolvedClip->mode);
-        auto clipRegion = reinterpret_cast<const ClipRegion*>(resolvedClip);
-        EXPECT_EQ(SkIRect::MakeLTRB(60, 20, 160, 200), clipRegion->region.getBounds());
-    }
-}
-
-TEST(ClipArea, serializeIntersectedClip_snap) {
-    ClipArea area(createClipArea());
-    area.setClip(100.2, 100.4, 500.6, 500.8);
-    LinearAllocator allocator;
-
-    {
-        // no recorded clip case
-        auto resolvedClip = area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity());
-        EXPECT_EQ(Rect(100, 100, 501, 501), resolvedClip->rect);
-    }
-    {
-        // recorded clip case
-        ClipRect recordedClip(Rect(100.12, 100.74));
-        Matrix4 translateScale;
-        translateScale.loadTranslate(100, 100, 0);
-        translateScale.scale(2, 3,
-                             1);  // recorded clip will have non-int coords, even after transform
-        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
-        ASSERT_NE(nullptr, resolvedClip);
-        EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
-        EXPECT_EQ(Rect(100, 100, 300, 402), resolvedClip->rect);
-    }
-}
-
-TEST(ClipArea, serializeIntersectedClip_scale) {
-    ClipArea area(createClipArea());
-    area.setClip(0, 0, 400, 400);
-    LinearAllocator allocator;
-
-    SkPath circlePath;
-    circlePath.addCircle(50, 50, 50);
-
-    ClipRegion recordedClip;
-    recordedClip.region.setPath(circlePath, SkRegion(SkIRect::MakeWH(100, 100)));
-    recordedClip.rect = Rect(100, 100);
-
-    Matrix4 translateScale;
-    translateScale.loadTranslate(100, 100, 0);
-    translateScale.scale(2, 2, 1);
-    auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
-
-    ASSERT_NE(nullptr, resolvedClip);
-    EXPECT_EQ(ClipMode::Region, resolvedClip->mode);
-    EXPECT_EQ(Rect(100, 100, 300, 300), resolvedClip->rect);
-    auto clipRegion = reinterpret_cast<const ClipRegion*>(resolvedClip);
-    EXPECT_EQ(SkIRect::MakeLTRB(100, 100, 300, 300), clipRegion->region.getBounds());
-}
-
-TEST(ClipArea, applyTransformToRegion_identity) {
-    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
-    ClipArea::applyTransformToRegion(Matrix4::identity(), &region);
-    EXPECT_TRUE(region.isRect());
-    EXPECT_EQ(SkIRect::MakeLTRB(1, 2, 3, 4), region.getBounds());
-}
-
-TEST(ClipArea, applyTransformToRegion_translate) {
-    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
-    Matrix4 transform;
-    transform.loadTranslate(10, 20, 0);
-    ClipArea::applyTransformToRegion(transform, &region);
-    EXPECT_TRUE(region.isRect());
-    EXPECT_EQ(SkIRect::MakeLTRB(11, 22, 13, 24), region.getBounds());
-}
-
-TEST(ClipArea, applyTransformToRegion_scale) {
-    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
-    Matrix4 transform;
-    transform.loadScale(2, 3, 1);
-    ClipArea::applyTransformToRegion(transform, &region);
-    EXPECT_TRUE(region.isRect());
-    EXPECT_EQ(SkIRect::MakeLTRB(2, 6, 6, 12), region.getBounds());
-}
-
-TEST(ClipArea, applyTransformToRegion_translateScale) {
-    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
-    Matrix4 transform;
-    transform.translate(10, 20);
-    transform.scale(2, 3, 1);
-    ClipArea::applyTransformToRegion(transform, &region);
-    EXPECT_TRUE(region.isRect());
-    EXPECT_EQ(SkIRect::MakeLTRB(12, 26, 16, 32), region.getBounds());
-}
-
-TEST(ClipArea, applyTransformToRegion_rotate90) {
-    SkRegion region(SkIRect::MakeLTRB(1, 2, 3, 4));
-    Matrix4 transform;
-    transform.loadRotate(90);
-    ClipArea::applyTransformToRegion(transform, &region);
-    EXPECT_TRUE(region.isRect());
-    EXPECT_EQ(SkIRect::MakeLTRB(-4, 1, -2, 3), region.getBounds());
-}
-
-}  // namespace uirenderer
-}  // namespace android
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 2926ef3..2c73940 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -32,6 +32,7 @@
 #include "pipeline/skia/SkiaRecordingCanvas.h"
 #include "renderthread/CanvasContext.h"
 #include "tests/common/TestUtils.h"
+#include "utils/Color.h"
 
 using namespace android;
 using namespace android::uirenderer;
diff --git a/libs/hwui/tests/unit/SnapshotTests.cpp b/libs/hwui/tests/unit/SnapshotTests.cpp
deleted file mode 100644
index 9d673c8..0000000
--- a/libs/hwui/tests/unit/SnapshotTests.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2016 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 <Snapshot.h>
-
-#include <tests/common/TestUtils.h>
-
-using namespace android::uirenderer;
-
-TEST(Snapshot, serializeIntersectedClip) {
-    auto actualRoot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(0, 0, 100, 100));
-    auto root = TestUtils::makeSnapshot(Matrix4::identity(), Rect(10, 10, 90, 90));
-    auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
-    root->previous = actualRoot.get();
-    child->previous = root.get();
-
-    LinearAllocator allocator;
-    ClipRect rect(Rect(0, 0, 75, 75));
-    {
-        auto intersectWithChild =
-                child->serializeIntersectedClip(allocator, &rect, Matrix4::identity());
-        ASSERT_NE(nullptr, intersectWithChild);
-        EXPECT_EQ(Rect(50, 50, 75, 75), intersectWithChild->rect) << "Expect intersect with child";
-    }
-
-    rect.intersectWithRoot = true;
-    {
-        auto intersectWithRoot =
-                child->serializeIntersectedClip(allocator, &rect, Matrix4::identity());
-        ASSERT_NE(nullptr, intersectWithRoot);
-        EXPECT_EQ(Rect(10, 10, 75, 75), intersectWithRoot->rect) << "Expect intersect with root";
-    }
-}
-
-TEST(Snapshot, applyClip) {
-    auto actualRoot = TestUtils::makeSnapshot(Matrix4::identity(), Rect(0, 0, 100, 100));
-    auto root = TestUtils::makeSnapshot(Matrix4::identity(), Rect(10, 10, 90, 90));
-    root->previous = actualRoot.get();
-
-    ClipRect rect(Rect(0, 0, 75, 75));
-    {
-        auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
-        child->previous = root.get();
-        child->applyClip(&rect, Matrix4::identity());
-
-        EXPECT_TRUE(child->getClipArea().isSimple());
-        EXPECT_EQ(Rect(50, 50, 75, 75), child->getRenderTargetClip());
-    }
-
-    {
-        rect.intersectWithRoot = true;
-        auto child = TestUtils::makeSnapshot(Matrix4::identity(), Rect(50, 50, 90, 90));
-        child->previous = root.get();
-        child->applyClip(&rect, Matrix4::identity());
-
-        EXPECT_TRUE(child->getClipArea().isSimple());
-        EXPECT_EQ(Rect(10, 10, 75, 75), child->getRenderTargetClip());
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 99a2cdc..80f3506 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -284,8 +284,8 @@
         super.onViewCreated(view, savedInstanceState);
         mNavigationBarView = (NavigationBarView) view;
 
-        mNavigationBarView.setDisabledFlags(mDisabledFlags1);
         mNavigationBarView.setComponents(mStatusBar.getPanel());
+        mNavigationBarView.setDisabledFlags(mDisabledFlags1);
         mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
         mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
         if (savedInstanceState != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index a97effd..e20e267 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -956,11 +956,13 @@
                 changed |= onVolumeChangedW(stream, 0);
             } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
                 final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
+                if (isInitialStickyBroadcast()) mState.ringerModeExternal = rm;
                 if (D.BUG) Log.d(TAG, "onReceive RINGER_MODE_CHANGED_ACTION rm="
                         + Util.ringerModeToString(rm));
                 changed = updateRingerModeExternalW(rm);
             } else if (action.equals(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION)) {
                 final int rm = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
+                if (isInitialStickyBroadcast()) mState.ringerModeInternal = rm;
                 if (D.BUG) Log.d(TAG, "onReceive INTERNAL_RINGER_MODE_CHANGED_ACTION rm="
                         + Util.ringerModeToString(rm));
                 changed = updateRingerModeInternalW(rm);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7abac00..798f8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -135,10 +135,6 @@
     private final AccessibilityManagerWrapper mAccessibilityMgr;
     private final Object mSafetyWarningLock = new Object();
     private final Accessibility mAccessibility = new Accessibility();
-    private ColorStateList mActiveTint;
-    private int mActiveAlpha;
-    private ColorStateList mInactiveTint;
-    private int mInactiveAlpha;
 
     private boolean mShowing;
     private boolean mShowA11yStream;
@@ -238,11 +234,6 @@
         lp.gravity = ((FrameLayout.LayoutParams) mDialogView.getLayoutParams()).gravity;
         mWindow.setAttributes(lp);
 
-        mActiveTint = Utils.getColorAccent(mContext);
-        mActiveAlpha = Color.alpha(mActiveTint.getDefaultColor());
-        mInactiveTint = Utils.getColorAttr(mContext, android.R.attr.colorForeground);
-        mInactiveAlpha = getAlphaAttr(android.R.attr.secondaryContentAlpha);
-
         mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
         mRinger = mDialog.findViewById(R.id.ringer);
         if (mRinger != null) {
@@ -942,8 +933,12 @@
             row.slider.requestFocus();
         }
         boolean useActiveColoring = isActive && row.slider.isEnabled();
-        final ColorStateList tint = useActiveColoring ? mActiveTint : mInactiveTint;
-        final int alpha = useActiveColoring ? mActiveAlpha : mInactiveAlpha;
+        final ColorStateList tint = useActiveColoring
+                ? Utils.getColorAccent(mContext)
+                : Utils.getColorAttr(mContext, android.R.attr.colorForeground);
+        final int alpha = useActiveColoring
+                ? Color.alpha(tint.getDefaultColor())
+                : getAlphaAttr(android.R.attr.secondaryContentAlpha);
         if (tint == row.cachedTint) return;
         row.slider.setProgressTintList(tint);
         row.slider.setThumbTintList(tint);
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index dd36867..f85749a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1813,8 +1813,6 @@
         return sanitizers;
     }
 
-    // TODO: this method is called a few times in the save process, we should cache its results into
-    // ViewState.
     @Nullable
     private AutofillValue getSanitizedValue(
             @Nullable ArrayMap<AutofillId, InternalSanitizer> sanitizers,
@@ -1822,13 +1820,22 @@
             @Nullable AutofillValue value) {
         if (sanitizers == null || value == null) return value;
 
-        final InternalSanitizer sanitizer = sanitizers.get(id);
-        if (sanitizer == null) {
-            return value;
-        }
+        final ViewState state = mViewStates.get(id);
+        AutofillValue sanitized = state == null ? null : state.getSanitizedValue();
+        if (sanitized == null) {
+            final InternalSanitizer sanitizer = sanitizers.get(id);
+            if (sanitizer == null) {
+                return value;
+            }
 
-        final AutofillValue sanitized = sanitizer.sanitize(value);
-        if (sDebug) Slog.d(TAG, "Value for " + id + "(" + value + ") sanitized to " + sanitized);
+            sanitized = sanitizer.sanitize(value);
+            if (sDebug) {
+                Slog.d(TAG, "Value for " + id + "(" + value + ") sanitized to " + sanitized);
+            }
+            if (state != null) {
+                state.setSanitizedValue(sanitized);
+            }
+        }
         return sanitized;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 877d1f4..5d2d902 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -21,7 +21,6 @@
 import static android.Manifest.permission.FILTER_EVENTS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.REMOVE_TASKS;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
 import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
@@ -29,9 +28,7 @@
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
 import static android.content.pm.PackageManager.GET_PROVIDERS;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
@@ -150,6 +147,8 @@
 import static com.android.server.am.ActivityTaskManagerService.DUMP_RECENTS_SHORT_CMD;
 import static com.android.server.am.ActivityTaskManagerService.DUMP_STARTER_CMD;
 import static com.android.server.am.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+import static com.android.server.am.ActivityTaskManagerService.relaunchReasonToString;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
 import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
@@ -166,7 +165,6 @@
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerProto;
-import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -369,18 +367,15 @@
 
 import libcore.util.EmptyArray;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
-import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -9783,9 +9778,9 @@
                         : StatsLog.APP_CRASH_OCCURRED__FOREGROUND_STATE__UNKNOWN
         );
 
-        final int relaunchReason = r == null ? ActivityRecord.RELAUNCH_REASON_NONE
+        final int relaunchReason = r == null ? RELAUNCH_REASON_NONE
                         : r.getWindowProcessController().computeRelaunchReason();
-        final String relaunchReasonString = ActivityRecord.relaunchReasonToString(relaunchReason);
+        final String relaunchReasonString = relaunchReasonToString(relaunchReason);
         if (crashInfo.crashTag == null) {
             crashInfo.crashTag = relaunchReasonString;
         } else {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 966cbd1..d8afe0b 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -81,6 +81,7 @@
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Process.SYSTEM_UID;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 
 import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
@@ -114,6 +115,9 @@
 import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
 import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
 import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
 import static com.android.server.am.TaskPersister.DEBUG;
@@ -338,12 +342,6 @@
     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
 
-    // This activity is not being relaunched, or being relaunched for a non-resize reason.
-    static final int RELAUNCH_REASON_NONE = 0;
-    // This activity is being relaunched due to windowing mode change.
-    static final int RELAUNCH_REASON_WINDOWING_MODE_RESIZE = 1;
-    // This activity is being relaunched due to a free-resize operation.
-    static final int RELAUNCH_REASON_FREE_RESIZE = 2;
     // Marking the reason why this activity is being relaunched. Mainly used to track that this
     // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
     // pre-NYC apps that don't have a sense of being resized.
@@ -2215,12 +2213,13 @@
     }
 
     /**
-     * @return display id to which this record is attached, -1 if not attached.
+     * @return display id to which this record is attached,
+     *         {@link android.view.Display#INVALID_DISPLAY} if not attached.
      */
     int getDisplayId() {
         final ActivityStack stack = getStack();
         if (stack == null) {
-            return -1;
+            return INVALID_DISPLAY;
         }
         return stack.mDisplayId;
     }
@@ -3010,17 +3009,6 @@
         mWindowContainerController.registerRemoteAnimations(definition);
     }
 
-    static String relaunchReasonToString(int relaunchReason) {
-        switch (relaunchReason) {
-            case RELAUNCH_REASON_WINDOWING_MODE_RESIZE:
-                return "window_resize";
-            case RELAUNCH_REASON_FREE_RESIZE:
-                return "free_resize";
-            default:
-                return null;
-        }
-    }
-
     @Override
     public String toString() {
         if (stringName != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 695ffe2..12ed726 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -81,8 +81,8 @@
 import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_FREE_RESIZE;
-import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c455704..12c6dec 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -75,7 +75,7 @@
 import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityTaskManagerService.ANIMATE;
 import static com.android.server.am.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG;
-import static com.android.server.am.ActivityRecord.RELAUNCH_REASON_NONE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
@@ -2258,9 +2258,9 @@
      * Finish the topmost activities in all stacks that belong to the crashed app.
      * @param app The app that crashed.
      * @param reason Reason to perform this action.
-     * @return The task that was finished in this stack, {@code null} if haven't found any.
+     * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
      */
-    TaskRecord finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) {
+    int finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) {
         TaskRecord finishedTask = null;
         ActivityStack focusedStack = getTopDisplayFocusedStack();
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
@@ -2275,7 +2275,7 @@
                 }
             }
         }
-        return finishedTask;
+        return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID;
     }
 
     void finishVoiceTask(IVoiceInteractionSession session) {
@@ -2466,7 +2466,7 @@
         }
         if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
             if (r != null) {
-                stack = (T) getValidLaunchStackOnDisplay(displayId, r, options);
+                stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options);
                 if (stack != null) {
                     return stack;
                 }
@@ -2531,10 +2531,11 @@
      * If there is no such stack, new dynamic stack can be created.
      * @param displayId Target display.
      * @param r Activity that should be launched there.
+     * @param candidateTask The possible task the activity might be put in.
      * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
      */
     ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
-            @Nullable ActivityOptions options) {
+            @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options) {
         final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException(
@@ -2545,6 +2546,13 @@
             return null;
         }
 
+        // If {@code r} is already in target display and its task is the same as the candidate task,
+        // the intention should be getting a launch stack for the reusable activity, so we can use
+        // the existing stack.
+        if (r.getDisplayId() == displayId && r.getTask() == candidateTask) {
+            return candidateTask.getStack();
+        }
+
         // Return the topmost valid stack on the display.
         for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
             final ActivityStack stack = activityDisplay.getChildAt(i);
@@ -2565,6 +2573,11 @@
         return null;
     }
 
+    ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+            @Nullable ActivityOptions options) {
+        return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options);
+    }
+
     // TODO: Can probably be consolidated into getLaunchStack()...
     private boolean isValidLaunchStack(ActivityStack stack, int displayId, ActivityRecord r) {
         switch (stack.getActivityType()) {
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index cb729a8..2d27017 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -277,7 +277,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Predicate;
 
 /**
  * System service for managing activities and their containers (task, stacks, displays,... ).
@@ -314,7 +313,15 @@
     public static final String DUMP_RECENTS_CMD = "recents" ;
     public static final String DUMP_RECENTS_SHORT_CMD = "r" ;
 
+    /** This activity is not being relaunched, or being relaunched for a non-resize reason. */
+    public static final int RELAUNCH_REASON_NONE = 0;
+    /** This activity is being relaunched due to windowing mode change. */
+    public static final int RELAUNCH_REASON_WINDOWING_MODE_RESIZE = 1;
+    /** This activity is being relaunched due to a free-resize operation. */
+    public static final int RELAUNCH_REASON_FREE_RESIZE = 2;
+
     Context mContext;
+
     /**
      * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can
      * change at runtime. Use mContext for non-UI purposes.
@@ -1362,7 +1369,7 @@
                         Slog.i(TAG, "Removing task failed to finish activity");
                     }
                     // Explicitly dismissing the activity so reset its relaunch flag.
-                    r.mRelaunchReason = ActivityRecord.RELAUNCH_REASON_NONE;
+                    r.mRelaunchReason = RELAUNCH_REASON_NONE;
                 } else {
                     res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                             resultData, "app-request", true);
@@ -4325,6 +4332,17 @@
         }
     }
 
+    public static String relaunchReasonToString(int relaunchReason) {
+        switch (relaunchReason) {
+            case RELAUNCH_REASON_WINDOWING_MODE_RESIZE:
+                return "window_resize";
+            case RELAUNCH_REASON_FREE_RESIZE:
+                return "free_resize";
+            default:
+                return null;
+        }
+    }
+
     ActivityStack getTopDisplayFocusedStack() {
         return mStackSupervisor.getTopDisplayFocusedStack();
     }
@@ -6642,5 +6660,12 @@
                 mStackSupervisor.handleAppCrashLocked(wpc);
             }
         }
+
+        @Override
+        public int finishTopCrashedActivities(WindowProcessController crashedApp, String reason) {
+            synchronized (mGlobalLock) {
+                return mStackSupervisor.finishTopCrashedActivitiesLocked(crashedApp, reason);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index cde633d..a80a5b5 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -63,7 +65,7 @@
         mService = service;
         mProc = data.proc;
         mResult = data.result;
-        mIsRestartable = (data.task != null || data.isRestartableForService)
+        mIsRestartable = (data.taskId != INVALID_TASK_ID || data.isRestartableForService)
                 && Settings.Global.getInt(context.getContentResolver(),
                 Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG, 0) != 0;
         BidiFormatter bidi = BidiFormatter.getInstance();
@@ -209,7 +211,7 @@
 
     static class Data {
         AppErrorResult result;
-        TaskRecord task;
+        int taskId;
         boolean repeating;
         ProcessRecord proc;
         boolean isRestartableForService;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index feea3bd..83c4ab5 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -16,12 +16,13 @@
 
 package com.android.server.am;
 
-import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.am.ActivityManagerService.SYSTEM_DEBUGGABLE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
@@ -46,21 +47,17 @@
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.StatsLog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.os.ProcessCpuTracker;
 import com.android.server.RescueParty;
 import com.android.server.Watchdog;
 
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Set;
 
@@ -411,11 +408,10 @@
         }
 
         final int relaunchReason = r != null
-                ? r.getWindowProcessController().computeRelaunchReason()
-                : ActivityRecord.RELAUNCH_REASON_NONE;
+                ? r.getWindowProcessController().computeRelaunchReason() : RELAUNCH_REASON_NONE;
 
         AppErrorResult result = new AppErrorResult();
-        TaskRecord task;
+        int taskId;
         synchronized (mService) {
             /**
              * If crash is handled by instance of {@link android.app.IActivityController},
@@ -428,7 +424,7 @@
 
             // Suppress crash dialog if the process is being relaunched due to a crash during a free
             // resize.
-            if (relaunchReason == ActivityRecord.RELAUNCH_REASON_FREE_RESIZE) {
+            if (relaunchReason == RELAUNCH_REASON_FREE_RESIZE) {
                 return;
             }
 
@@ -458,7 +454,7 @@
             final Message msg = Message.obtain();
             msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
 
-            task = data.task;
+            taskId = data.taskId;
             msg.obj = data;
             mService.mUiHandler.sendMessage(msg);
         }
@@ -476,24 +472,14 @@
             }
             if (res == AppErrorDialog.RESTART) {
                 mService.removeProcessLocked(r, false, true, "crash");
-                if (task != null) {
+                if (taskId != INVALID_TASK_ID) {
                     try {
-                        mService.mActivityTaskManager.startActivityFromRecents(task.taskId,
+                        mService.mActivityTaskManager.startActivityFromRecents(taskId,
                                 ActivityOptions.makeBasic().toBundle());
                     } catch (IllegalArgumentException e) {
-                        // Hmm, that didn't work, app might have crashed before creating a
-                        // recents entry. Let's see if we have a safe-to-restart intent.
-                        final Set<String> cats = task.intent != null
-                                ? task.intent.getCategories() : null;
-                        if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
-                            mService.mActivityTaskManager.getActivityStartController().startActivityInPackage(
-                                    task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
-                                    task.intent, null, null, null, 0, 0,
-                                    new SafeActivityOptions(ActivityOptions.makeBasic()),
-                                    task.userId, null,
-                                    "AppErrors", false /*validateIncomingUser*/,
-                                    null /* originatingPendingIntent */);
-                        }
+                        // Hmm...that didn't work. Task should either be in recents or associated
+                        // with a stack.
+                        Slog.e(TAG, "Could not restart taskId=" + taskId, e);
                     }
                 }
             }
@@ -736,11 +722,10 @@
             }
             mService.mAtmInternal.resumeTopActivities(false /* scheduleIdle */);
         } else {
-            final TaskRecord affectedTask =
-                    mService.mActivityTaskManager.mStackSupervisor.finishTopCrashedActivitiesLocked(
+            final int affectedTaskId = mService.mAtmInternal.finishTopCrashedActivities(
                             app.getWindowProcessController(), reason);
             if (data != null) {
-                data.task = affectedTask;
+                data.taskId = affectedTaskId;
             }
             if (data != null && crashTimePersistent != null
                     && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index 23ae77d..85ee7e6 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -46,6 +46,27 @@
     static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
             "/system/bin/statsd",  // Stats daemon.
             "/system/bin/surfaceflinger",
+            "/system/bin/apexd",  // APEX daemon.
+            "/system/bin/audioserver",
+            "/system/bin/cameraserver",
+            "/system/bin/drmserver",
+            "/system/bin/healthd",
+            "/system/bin/incidentd",
+            "/system/bin/installd",
+            "/system/bin/lmkd",  // Low memory killer daemon.
+            "/system/bin/logd",
+            "media.codec",
+            "media.extractor",
+            "media.metrics",
+            "/system/bin/mediadrmserver",
+            "/system/bin/mediaserver",
+            "/system/bin/performanced",
+            "/system/bin/tombstoned",
+            "/system/bin/traced",  // Perfetto.
+            "/system/bin/traced_probes",  // Perfetto.
+            "webview_zygote",
+            "zygote",
+            "zygote64",
     };
 
     static final int BYTES_IN_KILOBYTE = 1024;
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 0445cee..792b66b 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -32,6 +32,7 @@
 import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.am.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
 import static com.android.server.am.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 
 import android.app.Activity;
 import android.app.ActivityThread;
@@ -617,12 +618,12 @@
             final int activitiesSize = mActivities.size();
             for (int i = activitiesSize - 1; i >= 0; i--) {
                 final ActivityRecord r = mActivities.get(i);
-                if (r.mRelaunchReason != ActivityRecord.RELAUNCH_REASON_NONE) {
+                if (r.mRelaunchReason != RELAUNCH_REASON_NONE) {
                     return r.mRelaunchReason;
                 }
             }
         }
-        return ActivityRecord.RELAUNCH_REASON_NONE;
+        return RELAUNCH_REASON_NONE;
     }
 
     public long getInputDispatchingTimeout() {
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 4913e8b..c20079e 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -197,7 +197,7 @@
     private static native boolean nativeHasKeys(long ptr,
             int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
-            InputWindowHandle inputWindowHandle, boolean monitor);
+            InputWindowHandle inputWindowHandle, int displayId);
     private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
     private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
     private static native int nativeInjectInputEvent(long ptr, InputEvent event,
@@ -473,15 +473,21 @@
     /**
      * Creates an input channel that will receive all input from the input dispatcher.
      * @param inputChannelName The input channel name.
+     * @param displayId Target display id.
      * @return The input channel.
      */
-    public InputChannel monitorInput(String inputChannelName) {
+    public InputChannel monitorInput(String inputChannelName, int displayId) {
         if (inputChannelName == null) {
             throw new IllegalArgumentException("inputChannelName must not be null.");
         }
 
+        if (displayId < Display.DEFAULT_DISPLAY) {
+            throw new IllegalArgumentException("displayId must >= 0.");
+        }
+
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
+        // Register channel for monitor.
+        nativeRegisterInputChannel(mPtr, inputChannels[0], null, displayId);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -498,7 +504,8 @@
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
 
-        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
+        // Register channel for normal.
+        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, Display.INVALID_DISPLAY);
     }
 
     /**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 06ee935..dae7b01 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2061,7 +2061,8 @@
                     }
                 });
         mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
-        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
+        //TODO (b/111365687) : make system context per display.
+        mWindowManagerFuncs.registerPointerEventListener(mSystemGestures, DEFAULT_DISPLAY);
 
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
@@ -2258,13 +2259,16 @@
             WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
             wm.addView(mPointerLocationView, lp);
-            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView);
+            //TODO (b/111365687) : make system context per display.
+            mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView, DEFAULT_DISPLAY);
         }
     }
 
     private void disablePointerLocation() {
         if (mPointerLocationView != null) {
-            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView);
+            //TODO (b/111365687) : make system context per display.
+            mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView,
+                    DEFAULT_DISPLAY);
             WindowManager wm = (WindowManager) mContext.getSystemService(WINDOW_SERVICE);
             wm.removeView(mPointerLocationView);
             mPointerLocationView = null;
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 27ab3ef..2a8e523 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -559,10 +559,10 @@
         public Object getWindowManagerLock();
 
         /** Register a system listener for touch events */
-        void registerPointerEventListener(PointerEventListener listener);
+        void registerPointerEventListener(PointerEventListener listener, int displayId);
 
         /** Unregister a system listener for touch events */
-        void unregisterPointerEventListener(PointerEventListener listener);
+        void unregisterPointerEventListener(PointerEventListener listener, int displayId);
 
         /**
          * @return The content insets of the docked divider window.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 20099ca..7f9ee84 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -430,4 +430,13 @@
 
     /** Called whenever an app crashes. */
     public abstract void onHandleAppCrash(WindowProcessController wpc);
+
+    /**
+     * Finish the topmost activities in all stacks that belong to the crashed app.
+     * @param crashedApp The app that crashed.
+     * @param reason Reason to perform this action.
+     * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
+     */
+    public abstract int finishTopCrashedActivities(
+            WindowProcessController crashedApp, String reason);
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d8fd198..ca23360 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -145,12 +145,14 @@
 import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Gravity;
+import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.MagnificationSpec;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
+import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
@@ -454,6 +456,8 @@
      */
     WindowState mInputMethodWindow;
 
+    private final PointerEventDispatcher mPointerEventDispatcher;
+
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final AppWindowToken atoken = w.mAppToken;
@@ -833,6 +837,15 @@
         mDisplayReady = true;
 
         mInputMonitor = new InputMonitor(service, mDisplayId);
+
+        if (mService.mInputManager != null) {
+            final InputChannel inputChannel = mService.mInputManager.monitorInput("Display "
+                    + mDisplayId, mDisplayId);
+            mPointerEventDispatcher = inputChannel != null
+                    ? new PointerEventDispatcher(inputChannel) : null;
+        } else {
+            mPointerEventDispatcher = null;
+        }
     }
 
     boolean isReady() {
@@ -1286,6 +1299,19 @@
 
         mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
+
+        // Tap Listeners are supported for:
+        // 1. All physical displays (multi-display).
+        // 2. VirtualDisplays on VR, AA (and everything else).
+        if (mPointerEventDispatcher != null && mTapDetector == null) {
+            if (DEBUG_DISPLAY) {
+                Slog.d(TAG,
+                        "Registering PointerEventListener for DisplayId: " + mDisplayId);
+            }
+            mTapDetector = new TaskTapPointerEventListener(mService, this);
+            registerPointerEventListener(mTapDetector);
+            registerPointerEventListener(mService.mMousePositionTracker);
+        }
     }
 
     /**
@@ -2186,13 +2212,10 @@
         try {
             super.removeImmediately();
             if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
-            if (mService.canDispatchPointerEvents()) {
-                if (mTapDetector != null) {
-                    mService.unregisterPointerEventListener(mTapDetector);
-                }
-                if (mDisplayId == DEFAULT_DISPLAY && mService.mMousePositionTracker != null) {
-                    mService.unregisterPointerEventListener(mService.mMousePositionTracker);
-                }
+            if (mPointerEventDispatcher != null && mTapDetector != null) {
+                unregisterPointerEventListener(mTapDetector);
+                unregisterPointerEventListener(mService.mMousePositionTracker);
+                mTapDetector = null;
             }
             mService.mAnimator.removeDisplayLocked(mDisplayId);
             mWindowingLayer.release();
@@ -4409,4 +4432,16 @@
     boolean getLastHasContent() {
         return mLastHasContent;
     }
+
+    void registerPointerEventListener(@NonNull PointerEventListener listener) {
+        if (mPointerEventDispatcher != null) {
+            mPointerEventDispatcher.registerInputEventListener(listener);
+        }
+    }
+
+    void unregisterPointerEventListener(@NonNull PointerEventListener listener) {
+        if (mPointerEventDispatcher != null) {
+            mPointerEventDispatcher.unregisterInputEventListener(listener);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3fef87d..c8977be 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -228,21 +228,6 @@
             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
                     displayId, dc.getDisplayInfo());
             dc.configureDisplayPolicy();
-
-            // Tap Listeners are supported for:
-            // 1. All physical displays (multi-display).
-            // 2. VirtualDisplays on VR, AA (and everything else).
-            if (mService.canDispatchPointerEvents()) {
-                if (DEBUG_DISPLAY) {
-                    Slog.d(TAG,
-                            "Registering PointerEventListener for DisplayId: " + displayId);
-                }
-                dc.mTapDetector = new TaskTapPointerEventListener(mService, dc);
-                mService.registerPointerEventListener(dc.mTapDetector);
-                if (displayId == DEFAULT_DISPLAY) {
-                    mService.registerPointerEventListener(mService.mMousePositionTracker);
-                }
-            }
         }
 
         return dc;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ad51b17..7342ba1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -753,8 +753,6 @@
     final ArrayMap<AnimationAdapter, SurfaceAnimator> mAnimationTransferMap = new ArrayMap<>();
     final BoundsAnimationController mBoundsAnimationController;
 
-    private final PointerEventDispatcher mPointerEventDispatcher;
-
     private WindowContentFrameStats mTempWindowRenderStats;
 
     private final LatencyTracker mLatencyTracker;
@@ -945,14 +943,6 @@
 
         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
 
-        if(mInputManager != null) {
-            final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
-            mPointerEventDispatcher = inputChannel != null
-                    ? new PointerEventDispatcher(inputChannel) : null;
-        } else {
-            mPointerEventDispatcher = null;
-        }
-
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
 
         mKeyguardDisableHandler = new KeyguardDisableHandler(mContext, mPolicy);
@@ -3126,18 +3116,23 @@
     }
 
     @Override
-    public void registerPointerEventListener(PointerEventListener listener) {
-        mPointerEventDispatcher.registerInputEventListener(listener);
+    public void registerPointerEventListener(PointerEventListener listener, int displayId) {
+        synchronized (mWindowMap) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent != null) {
+                displayContent.registerPointerEventListener(listener);
+            }
+        }
     }
 
     @Override
-    public void unregisterPointerEventListener(PointerEventListener listener) {
-        mPointerEventDispatcher.unregisterInputEventListener(listener);
-    }
-
-    /** Check if the service is set to dispatch pointer events. */
-    boolean canDispatchPointerEvents() {
-        return mPointerEventDispatcher != null;
+    public void unregisterPointerEventListener(PointerEventListener listener, int displayId) {
+        synchronized (mWindowMap) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent != null) {
+                displayContent.unregisterPointerEventListener(listener);
+            }
+        }
     }
 
     // Called by window manager policy. Not exposed externally.
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 045f4eb..15a3a1a3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -99,6 +99,7 @@
         "libutils",
         "libhwui",
         "libbpf",
+        "libnetdbpf",
         "libnetdutils",
         "android.hardware.audio.common@2.0",
         "android.hardware.broadcastradio@1.0",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index c66d03c..3943dba 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -217,7 +217,7 @@
     void setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
+            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
@@ -442,11 +442,11 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
-        const sp<InputChannel>& inputChannel,
-        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
+        const sp<InputChannel>& inputChannel, const sp<InputWindowHandle>& inputWindowHandle,
+                int32_t displayId) {
     ATRACE_CALL();
-    return mInputManager->getDispatcher()->registerInputChannel(
-            inputChannel, inputWindowHandle, monitor);
+    return mInputManager->getDispatcher()->registerInputChannel(inputChannel, inputWindowHandle,
+            displayId);
 }
 
 status_t NativeInputManager::unregisterInputChannel(JNIEnv* /* env */,
@@ -1316,7 +1316,7 @@
 }
 
 static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
-        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
+        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jint displayId) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
@@ -1330,7 +1330,7 @@
             android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
 
     status_t status = im->registerInputChannel(
-            env, inputChannel, inputWindowHandle, monitor);
+            env, inputChannel, inputWindowHandle, displayId);
     if (status) {
         std::string message;
         message += StringPrintf("Failed to register input channel.  status=%d", status);
@@ -1338,7 +1338,8 @@
         return;
     }
 
-    if (! monitor) {
+    // If inputWindowHandle is null and displayId >= 0, treat inputChannel as monitor.
+    if (inputWindowHandle != nullptr || displayId == ADISPLAY_ID_NONE) {
         android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
                 handleInputChannelDisposed, im);
     }
@@ -1639,7 +1640,7 @@
     { "nativeHasKeys", "(JII[I[Z)Z",
             (void*) nativeHasKeys },
     { "nativeRegisterInputChannel",
-            "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
+            "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;I)V",
             (void*) nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
             (void*) nativeUnregisterInputChannel },
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 3302dea..649f1a5 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -30,8 +30,8 @@
 #include <utils/Log.h>
 
 #include "android-base/unique_fd.h"
-#include "bpf/BpfNetworkStats.h"
 #include "bpf/BpfUtils.h"
+#include "netdbpf/BpfNetworkStats.h"
 
 using android::bpf::Stats;
 using android::bpf::hasBpfSupport;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 062c044..ba64b51 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -37,6 +37,7 @@
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 
 import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
+import static com.android.server.am.ActivityDisplay.POSITION_TOP;
 import static com.android.server.am.ActivityTaskManagerService.ANIMATE;
 
 import static org.junit.Assert.assertEquals;
@@ -562,23 +563,13 @@
                 false /* mockGetLaunchStack */);
 
         // Create a secondary display at bottom.
-        final TestActivityDisplay secondaryDisplay = spy(addNewActivityDisplayAt(POSITION_BOTTOM));
+        final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay());
+        mSupervisor.addChild(secondaryDisplay, POSITION_BOTTOM);
         final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         // Create an activity record on the top of secondary display.
-        final ComponentName componentName = ComponentName.createRelative(
-                DEFAULT_COMPONENT_PACKAGE_NAME,
-                DEFAULT_COMPONENT_PACKAGE_NAME + ".ReusableActivity");
-        final TaskRecord taskRecord = new TaskBuilder(mSupervisor)
-                .setComponent(componentName)
-                .setStack(stack)
-                .build();
-        final ActivityRecord topActivityOnSecondaryDisplay = new ActivityBuilder(mService)
-                .setComponent(componentName)
-                .setLaunchMode(LAUNCH_SINGLE_TASK)
-                .setTask(taskRecord)
-                .build();
+        final ActivityRecord topActivityOnSecondaryDisplay = createSingleTaskActivityOn(stack);
 
         // Put an activity on default display as the top focused activity.
         new ActivityBuilder(mService).setCreateTask(true).build();
@@ -600,6 +591,59 @@
     }
 
     /**
+     * This test ensures that when starting an existing non-top single task activity on secondary
+     * display which is the top focused display, it should bring the task to front without creating
+     * unused stack.
+     */
+    @Test
+    public void testBringTaskToFrontOnSecondaryDisplay() {
+        final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK,
+                false /* mockGetLaunchStack */);
+
+        // Create a secondary display with an activity.
+        final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay());
+        mSupervisor.addChild(secondaryDisplay, POSITION_TOP);
+        final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
+                secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
+                        ACTIVITY_TYPE_STANDARD, false /* onTop */));
+
+        // Create another activity on top of the secondary display.
+        final ActivityStack topStack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        final TaskRecord topTask = new TaskBuilder(mSupervisor).setStack(topStack).build();
+        new ActivityBuilder(mService).setTask(topTask).build();
+
+        // Start activity with the same intent as {@code singleTaskActivity} on secondary display.
+        final ActivityOptions options = ActivityOptions.makeBasic()
+                .setLaunchDisplayId(secondaryDisplay.mDisplayId);
+        final int result = starter.setReason("testBringTaskToFrontOnSecondaryDisplay")
+                .setIntent(singleTaskActivity.intent)
+                .setActivityOptions(options.toBundle())
+                .execute();
+
+        // Ensure result is moving existing task to front.
+        assertEquals(START_TASK_TO_FRONT, result);
+
+        // Ensure secondary display only creates two stacks.
+        verify(secondaryDisplay, times(2)).createStack(anyInt(), anyInt(), anyBoolean());
+    }
+
+    private ActivityRecord createSingleTaskActivityOn(ActivityStack stack) {
+        final ComponentName componentName = ComponentName.createRelative(
+                DEFAULT_COMPONENT_PACKAGE_NAME,
+                DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity");
+        final TaskRecord taskRecord = new TaskBuilder(mSupervisor)
+                .setComponent(componentName)
+                .setStack(stack)
+                .build();
+        return new ActivityBuilder(mService)
+                .setComponent(componentName)
+                .setLaunchMode(LAUNCH_SINGLE_TASK)
+                .setTask(taskRecord)
+                .build();
+    }
+
+    /**
      * This test ensures that a reused top activity in the top focused stack is able to be
      * reparented to another display.
      */
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 3dcdd23..cb8ca7e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -39,6 +39,7 @@
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doNothing;
@@ -288,34 +289,25 @@
         final WindowTestUtils.TestAppWindowToken token =
                 WindowTestUtils.createTestAppWindowToken(dc0);
         task0.addChild(token, 0);
-        dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
-        sWm.registerPointerEventListener(dc0.mTapDetector);
+        dc0.configureDisplayPolicy();
+        assertNotNull(dc0.mTapDetector);
+
         final TaskStack stack1 = createTaskStackOnDisplay(dc1);
         final Task task1 = createTaskInStack(stack1, 0 /* userId */);
         final WindowTestUtils.TestAppWindowToken token1 =
                 WindowTestUtils.createTestAppWindowToken(dc0);
         task1.addChild(token1, 0);
-        dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
-        sWm.registerPointerEventListener(dc1.mTapDetector);
+        dc1.configureDisplayPolicy();
+        assertNotNull(dc1.mTapDetector);
 
-        // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
-        DisplayMetrics dm0 = dc0.getDisplayMetrics();
-        dc0.mTapDetector.onPointerEvent(
-                createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
-        dc0.mTapDetector.onPointerEvent(
-                createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
-
+        // tap on primary display.
+        tapOnDisplay(dc0);
         // Check focus is on primary display.
         assertEquals(sWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
                 dc0.findFocusedWindow());
 
-        // Tap on secondary display
-        DisplayMetrics dm1 = dc1.getDisplayMetrics();
-        dc1.mTapDetector.onPointerEvent(
-                createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
-        dc1.mTapDetector.onPointerEvent(
-                createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
-
+        // Tap on secondary display.
+        tapOnDisplay(dc1);
         // Check focus is on secondary.
         assertEquals(sWm.mRoot.getTopFocusedDisplayContent().mCurrentFocus,
                 dc1.findFocusedWindow());
@@ -626,17 +618,32 @@
         return result;
     }
 
-    private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
+    private void tapOnDisplay(final DisplayContent dc) {
+        final DisplayMetrics dm = dc.getDisplayMetrics();
+        final float x = dm.widthPixels / 2;
+        final float y = dm.heightPixels / 2;
         final long downTime = SystemClock.uptimeMillis();
         final long eventTime = SystemClock.uptimeMillis() + 100;
-        final int metaState = 0;
-
-        return MotionEvent.obtain(
+        // sending ACTION_DOWN
+        final MotionEvent downEvent = MotionEvent.obtain(
                 downTime,
-                eventTime,
-                isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
+                downTime,
+                MotionEvent.ACTION_DOWN,
                 x,
                 y,
-                metaState);
+                0 /*metaState*/);
+        downEvent.setDisplayId(dc.getDisplayId());
+        dc.mTapDetector.onPointerEvent(downEvent);
+
+        // sending ACTION_UP
+        final MotionEvent upEvent = MotionEvent.obtain(
+                downTime,
+                eventTime,
+                MotionEvent.ACTION_UP,
+                x,
+                y,
+                0 /*metaState*/);
+        upEvent.setDisplayId(dc.getDisplayId());
+        dc.mTapDetector.onPointerEvent(upEvent);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index 54fd7db..389eba5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -34,8 +34,8 @@
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.view.InputChannel;
-
-import androidx.test.InstrumentationRegistry;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
 
 import com.android.server.LocalServices;
 import com.android.server.input.InputManagerService;
@@ -46,6 +46,12 @@
 import org.junit.runners.model.Statement;
 import org.mockito.invocation.InvocationOnMock;
 
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.test.InstrumentationRegistry;
+
 /**
  * A test rule that sets up a fresh WindowManagerService instance before each test and makes sure
  * to properly tear it down after.
@@ -61,6 +67,12 @@
 
     private WindowManagerService mService;
     private TestWindowManagerPolicy mPolicy;
+    // Record all {@link SurfaceControl.Transaction} created while testing and releases native
+    // resources when test finishes.
+    private final List<WeakReference<Transaction>> mSurfaceTransactions = new ArrayList<>();
+    // Record all {@link SurfaceControl} created while testing and releases native resources when
+    // test finishes.
+    private final List<WeakReference<SurfaceControl>> mSurfaceControls = new ArrayList<>();
 
     @Override
     public Statement apply(Statement base, Description description) {
@@ -108,12 +120,25 @@
                 // InputChannel is final and can't be mocked.
                 InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
                 if (input != null && input.length > 1) {
-                    doReturn(input[1]).when(ims).monitorInput(anyString());
+                    doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt());
                 }
 
                 mService = WindowManagerService.main(context, ims, false,
                         false, mPolicy = new TestWindowManagerPolicy(
                                 WindowManagerServiceRule.this::getWindowManagerService));
+                mService.mTransactionFactory = () -> {
+                    final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+                    mSurfaceTransactions.add(new WeakReference<>(transaction));
+                    return transaction;
+                };
+                mService.mSurfaceBuilderFactory = session -> new SurfaceControl.Builder(session) {
+                    @Override
+                    public SurfaceControl build() {
+                        final SurfaceControl control = super.build();
+                        mSurfaceControls.add(new WeakReference<>(control));
+                        return control;
+                    }
+                };
 
                 mService.onInitReady();
 
@@ -135,6 +160,8 @@
 
             private void tearDown() {
                 waitUntilWindowManagerHandlersIdle();
+                destroyAllSurfaceTransactions();
+                destroyAllSurfaceControls();
                 removeServices();
                 mService = null;
                 mPolicy = null;
@@ -158,4 +185,24 @@
             SurfaceAnimationThread.getHandler().runWithScissors(() -> { }, 0);
         }
     }
+
+    private void destroyAllSurfaceTransactions() {
+        for (final WeakReference<Transaction> reference : mSurfaceTransactions) {
+            final Transaction transaction = reference.get();
+            if (transaction != null) {
+                reference.clear();
+                transaction.close();
+            }
+        }
+    }
+
+    private void destroyAllSurfaceControls() {
+        for (final WeakReference<SurfaceControl> reference : mSurfaceControls) {
+            final SurfaceControl control = reference.get();
+            if (control != null) {
+                reference.clear();
+                control.destroy();
+            }
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index a610e6e..3a8c4ae 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -98,10 +98,13 @@
             super(s);
         }
 
+        @Override
         public SurfaceControl.Builder setParent(SurfaceControl sc) {
             mPendingParent = sc;
             return super.setParent(sc);
         }
+
+        @Override
         public SurfaceControl build() {
             SurfaceControl sc = super.build();
             mParentFor.put(sc, mPendingParent);
@@ -110,7 +113,7 @@
         }
     }
 
-    class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
+    private class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
         public SurfaceControl.Builder make(SurfaceSession s) {
             return new HierarchyRecorder(s);
         }
@@ -131,6 +134,7 @@
     @After
     public void after() {
         mTransaction.close();
+        mParentFor.keySet().forEach(SurfaceControl::destroy);
         mParentFor.clear();
     }
 
diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java
index 5bf94af..32fc796 100644
--- a/services/usb/java/com/android/server/usb/UsbSerialReader.java
+++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java
@@ -75,14 +75,21 @@
         if (uid != Process.SYSTEM_UID) {
             enforcePackageBelongsToUid(uid, packageName);
 
-            PackageInfo pkg;
+            int packageTargetSdkVersion;
+            long token = Binder.clearCallingIdentity();
             try {
-                pkg = mContext.getPackageManager().getPackageInfo(packageName, 0);
-            } catch (PackageManager.NameNotFoundException e) {
-                throw new RemoteException("package " + packageName + " cannot be found");
+                PackageInfo pkg;
+                try {
+                    pkg = mContext.getPackageManager().getPackageInfo(packageName, 0);
+                } catch (PackageManager.NameNotFoundException e) {
+                    throw new RemoteException("package " + packageName + " cannot be found");
+                }
+                packageTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
 
-            if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+            if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) {
                 if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid)
                         == PackageManager.PERMISSION_DENIED) {
                     UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser(
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 8454d12..1efa906 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -3524,6 +3524,18 @@
         public static final String CARRIER_ID = "carrier_id";
 
         /**
+         * A unique mno carrier id. mno carrier shares the same {@link All#MCCMNC} as carrier id
+         * and can be solely identified by {@link All#MCCMNC} only. If there is no such mno
+         * carrier, then mno carrier id equals to {@link #CARRIER_ID carrier id}.
+         *
+         * <p>mno carrier id can be used as fallback id. When the exact carrier id configurations
+         * are not found, usually fall back to its mno carrier id.
+         * <P>Type: INTEGER </P>
+         * @hide
+         */
+        public static final String MNO_CARRIER_ID = "mno_carrier_id";
+
+        /**
          * Contains mappings between matching rules with carrier id for all carriers.
          * @hide
          */
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index fac1943..08b5c2d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1965,6 +1965,31 @@
     public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
 
     /**
+     * Indicates if the carrier supports auto-upgrading a call to RTT when receiving a call from a
+     * RTT-supported device.
+     * @hide
+     */
+    public static final String KEY_RTT_AUTO_UPGRADE_BOOL = "rtt_auto_upgrade_bool";
+
+    /**
+     * Indicates if the carrier supports RTT during a video call.
+     * @hide
+     */
+    public static final String KEY_RTT_SUPPORTED_FOR_VT_BOOL = "rtt_supported_for_vt_bool";
+
+    /**
+     * Indicates if the carrier supports upgrading a voice call to an RTT call during the call.
+     * @hide
+     */
+    public static final String KEY_RTT_UPGRADE_SUPPORTED_BOOL = "rtt_upgrade_supported_bool";
+
+    /**
+     * Indicates if the carrier supports downgrading a RTT call to a voice call during the call.
+     * @hide
+     */
+    public static final String KEY_RTT_DOWNGRADE_SUPPORTED_BOOL = "rtt_downgrade_supported_bool";
+
+    /**
      * The flag to disable the popup dialog which warns the user of data charges.
      * @hide
      */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8f78c34..d6a0ae1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1163,6 +1163,16 @@
     public static final String EXTRA_CARRIER_ID = "android.telephony.extra.CARRIER_ID";
 
     /**
+     * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which indicates
+     * the updated mno carrier id of the current subscription.
+     * <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
+     * the carrier cannot be identified.
+     *
+     *@hide
+     */
+    public static final String EXTRA_MNO_CARRIER_ID = "android.telephony.extra.MNO_CARRIER_ID";
+
+    /**
      * An string extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which
      * indicates the updated carrier name of the current subscription.
      * {@see TelephonyManager#getSimCarrierIdName()}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index eb144f9..aabefe3 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -257,7 +257,7 @@
 
     private final int mProfileId;
 
-    private final boolean mModemCognitive;
+    private final boolean mPersistent;
     private final int mMaxConns;
     private final int mWaitTime;
     private final int mMaxConnsTime;
@@ -290,13 +290,13 @@
     }
 
     /**
-     * Returns if the APN setting is to be set in modem.
+     * Returns if the APN setting is persistent on the modem.
      *
      * @return is the APN setting to be set in modem
      * @hide
      */
-    public boolean getModemCognitive() {
-        return mModemCognitive;
+    public boolean isPersistent() {
+        return mPersistent;
     }
 
     /**
@@ -616,7 +616,7 @@
         this.mCarrierEnabled = builder.mCarrierEnabled;
         this.mNetworkTypeBitmask = builder.mNetworkTypeBitmask;
         this.mProfileId = builder.mProfileId;
-        this.mModemCognitive = builder.mModemCognitive;
+        this.mPersistent = builder.mModemCognitive;
         this.mMaxConns = builder.mMaxConns;
         this.mWaitTime = builder.mWaitTime;
         this.mMaxConnsTime = builder.mMaxConnsTime;
@@ -740,7 +740,7 @@
                 apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
                 apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
                 apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
-                apn.mProfileId, apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime,
+                apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
                 apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
     }
 
@@ -947,7 +947,7 @@
         sb.append(", ").append(PROTOCOL_INT_MAP.get(mRoamingProtocol));
         sb.append(", ").append(mCarrierEnabled);
         sb.append(", ").append(mProfileId);
-        sb.append(", ").append(mModemCognitive);
+        sb.append(", ").append(mPersistent);
         sb.append(", ").append(mMaxConns);
         sb.append(", ").append(mWaitTime);
         sb.append(", ").append(mMaxConnsTime);
@@ -1029,7 +1029,7 @@
                 && Objects.equals(mMmsc, other.mMmsc)
                 && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
                 && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-                && Objects.equals(mProxyPort,other.mProxyPort)
+                && Objects.equals(mProxyPort, other.mProxyPort)
                 && Objects.equals(mUser, other.mUser)
                 && Objects.equals(mPassword, other.mPassword)
                 && Objects.equals(mAuthType, other.mAuthType)
@@ -1038,7 +1038,7 @@
                 && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
                 && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
                 && Objects.equals(mProfileId, other.mProfileId)
-                && Objects.equals(mModemCognitive, other.mModemCognitive)
+                && Objects.equals(mPersistent, other.mPersistent)
                 && Objects.equals(mMaxConns, other.mMaxConns)
                 && Objects.equals(mWaitTime, other.mWaitTime)
                 && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
@@ -1080,11 +1080,11 @@
                 && Objects.equals(mPassword, other.mPassword)
                 && Objects.equals(mAuthType, other.mAuthType)
                 && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-                && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+                && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
                 && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
                 && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
                 && Objects.equals(mProfileId, other.mProfileId)
-                && Objects.equals(mModemCognitive, other.mModemCognitive)
+                && Objects.equals(mPersistent, other.mPersistent)
                 && Objects.equals(mMaxConns, other.mMaxConns)
                 && Objects.equals(mWaitTime, other.mWaitTime)
                 && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index e8597b2..da4822c 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -68,17 +68,15 @@
 
     private final int mMtu;
 
-    private final String mMvnoType;
+    private final boolean mPersistent;
 
-    private final String mMvnoMatchData;
+    private final boolean mPreferred;
 
-    private final boolean mModemCognitive;
-
-    public DataProfile(int profileId, String apn, String protocol, int authType,
-                String userName, String password, int type, int maxConnsTime, int maxConns,
-                int waitTime, boolean enabled, int supportedApnTypesBitmap, String roamingProtocol,
-                int bearerBitmap, int mtu, String mvnoType, String mvnoMatchData,
-                boolean modemCognitive) {
+    /** @hide */
+    public DataProfile(int profileId, String apn, String protocol, int authType, String userName,
+                       String password, int type, int maxConnsTime, int maxConns, int waitTime,
+                       boolean enabled, int supportedApnTypesBitmap, String roamingProtocol,
+                       int bearerBitmap, int mtu, boolean persistent, boolean preferred) {
 
         this.mProfileId = profileId;
         this.mApn = apn;
@@ -100,11 +98,11 @@
         this.mRoamingProtocol = roamingProtocol;
         this.mBearerBitmap = bearerBitmap;
         this.mMtu = mtu;
-        this.mMvnoType = mvnoType;
-        this.mMvnoMatchData = mvnoMatchData;
-        this.mModemCognitive = modemCognitive;
+        this.mPersistent = persistent;
+        this.mPreferred = preferred;
     }
 
+    /** @hide */
     public DataProfile(Parcel source) {
         mProfileId = source.readInt();
         mApn = source.readString();
@@ -121,9 +119,8 @@
         mRoamingProtocol = source.readString();
         mBearerBitmap = source.readInt();
         mMtu = source.readInt();
-        mMvnoType = source.readString();
-        mMvnoMatchData = source.readString();
-        mModemCognitive = source.readBoolean();
+        mPersistent = source.readBoolean();
+        mPreferred = source.readBoolean();
     }
 
     /**
@@ -207,23 +204,17 @@
     public int getMtu() { return mMtu; }
 
     /**
-     * @return The MVNO type: possible values are "imsi", "gid", "spn".
+     * @return {@code true} if modem must persist this data profile.
      */
-    public String getMvnoType() { return mMvnoType; }
+    public boolean isPersistent() { return mPersistent; }
 
     /**
-     * @return The MVNO match data. For example,
-     * SPN: A MOBILE, BEN NL, ...
-     * IMSI: 302720x94, 2060188, ...
-     * GID: 4E, 33, ...
+     * @return {@code true} if this data profile was used to bring up the last default
+     * (i.e internet) data connection successfully.
      */
-    public String getMvnoMatchData() { return mMvnoMatchData; }
+    public boolean isPreferred() { return  mPreferred; }
 
-    /**
-     * @return True if the data profile was sent to the modem through setDataProfile earlier.
-     */
-    public boolean isModemCognitive() { return mModemCognitive; }
-
+    /** @hide */
     @Override
     public int describeContents() {
         return 0;
@@ -233,11 +224,11 @@
     public String toString() {
         return "DataProfile=" + mProfileId + "/" + mProtocol + "/" + mAuthType
                 + "/" + (Build.IS_USER ? "***/***/***" :
-                         (mApn + "/" + mUserName + "/" + mPassword))
-                + "/" + mType + "/" + mMaxConnsTime
-                + "/" + mMaxConns + "/" + mWaitTime + "/" + mEnabled + "/"
-                + mSupportedApnTypesBitmap + "/" + mRoamingProtocol + "/" + mBearerBitmap + "/"
-                + mMtu + "/" + mMvnoType + "/" + mMvnoMatchData + "/" + mModemCognitive;
+                         (mApn + "/" + mUserName + "/" + mPassword)) + "/" + mType + "/"
+                + mMaxConnsTime + "/" + mMaxConns + "/"
+                + mWaitTime + "/" + mEnabled + "/" + mSupportedApnTypesBitmap + "/"
+                + mRoamingProtocol + "/" + mBearerBitmap + "/" + mMtu + "/" + mPersistent + "/"
+                + mPreferred;
     }
 
     @Override
@@ -246,6 +237,7 @@
         return (o == this || toString().equals(o.toString()));
     }
 
+    /** @hide */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mProfileId);
@@ -263,11 +255,11 @@
         dest.writeString(mRoamingProtocol);
         dest.writeInt(mBearerBitmap);
         dest.writeInt(mMtu);
-        dest.writeString(mMvnoType);
-        dest.writeString(mMvnoMatchData);
-        dest.writeBoolean(mModemCognitive);
+        dest.writeBoolean(mPersistent);
+        dest.writeBoolean(mPreferred);
     }
 
+    /** @hide */
     public static final Parcelable.Creator<DataProfile> CREATOR =
             new Parcelable.Creator<DataProfile>() {
         @Override
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index d6a08543..bdba8c8 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -33,7 +33,7 @@
  * A parcelable class that wraps and retrieves the information of number, service category(s) and
  * country code for a specific emergency number.
  */
-public final class EmergencyNumber implements Parcelable {
+public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNumber> {
 
     private static final String LOG_TAG = "EmergencyNumber";
 
@@ -235,20 +235,22 @@
     }
 
     /**
-     * Returns the bitmask of emergency service categories {@link EmergencyServiceCategories} of
-     * the emergency number.
+     * Returns the bitmask of emergency service categories of the emergency number.
      *
-     * @return bitmask of the emergency service categories {@link EmergencyServiceCategories}
+     * @return bitmask of the emergency service categories
      */
     public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmask() {
         return mEmergencyServiceCategoryBitmask;
     }
 
     /**
-     * Returns the emergency service categories {@link EmergencyServiceCategories} of the emergency
-     * number.
+     * Returns the emergency service categories of the emergency number.
      *
-     * @return a list of the emergency service categories {@link EmergencyServiceCategories}
+     * Note: if the emergency number is in {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}, only
+     * {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} is returned and it means the number is in
+     * all categories.
+     *
+     * @return a list of the emergency service categories
      */
     public List<Integer> getEmergencyServiceCategories() {
         List<Integer> categories = new ArrayList<>();
@@ -276,34 +278,37 @@
     }
 
     /**
-     * Checks if the emergency number is in the specified emergency service category(s)
-     * {@link EmergencyServiceCategories}.
+     * Checks if the emergency number is in the supplied emergency service category(s).
+     *
+     * @param categories - the supplied emergency service categories
      *
      * @return {@code true} if the emergency number is in the specified emergency service
-     * category(s) {@link EmergencyServiceCategories}; {@code false} otherwise.
-     *
-     * @param categories - emergency service categories {@link EmergencyServiceCategories}
+     * category(s) or if its emergency service category is
+     * {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}; {@code false} otherwise.
      */
     public boolean isInEmergencyServiceCategories(@EmergencyServiceCategories int categories) {
         if (categories == EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED) {
             return serviceUnspecified();
         }
+        if (serviceUnspecified()) {
+            return true;
+        }
         return (mEmergencyServiceCategoryBitmask & categories) == categories;
     }
 
     /**
-     * Returns the bitmask of the sources {@link EmergencyNumberSources} of the emergency number.
+     * Returns the bitmask of the sources of the emergency number.
      *
-     * @return bitmask of the emergency number sources {@link EmergencyNumberSources}
+     * @return bitmask of the emergency number sources
      */
     public @EmergencyNumberSources int getEmergencyNumberSourceBitmask() {
         return mEmergencyNumberSourceBitmask;
     }
 
     /**
-     * Returns a list of {@link EmergencyNumberSources} of the emergency number.
+     * Returns a list of sources of the emergency number.
      *
-     * @return a list of {@link EmergencyNumberSources}
+     * @return a list of emergency number sources
      */
     public List<Integer> getEmergencyNumberSources() {
         List<Integer> sources = new ArrayList<>();
@@ -316,13 +321,12 @@
     }
 
     /**
-     * Checks if the emergency number is from the specified emergency number source(s)
-     * {@link EmergencyNumberSources}.
+     * Checks if the emergency number is from the specified emergency number source(s).
      *
      * @return {@code true} if the emergency number is from the specified emergency number
-     * source(s) {@link EmergencyNumberSources}; {@code false} otherwise.
+     * source(s); {@code false} otherwise.
      *
-     * @param sources - {@link EmergencyNumberSources}
+     * @param sources - the supplied emergency number sources
      */
     public boolean isFromSources(@EmergencyNumberSources int sources) {
         return (mEmergencyNumberSourceBitmask & sources) == sources;
@@ -359,6 +363,62 @@
         return (o == this || toString().equals(o.toString()));
     }
 
+    /**
+     * Calculate the score for display priority.
+     *
+     * A higher display priority score means the emergency number has a higher display priority.
+     * The score is higher if the source is defined for a higher display priority.
+     *
+     * The priority of sources are defined as follows:
+     *     EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING >
+     *     EMERGENCY_NUMBER_SOURCE_SIM >
+     *     EMERGENCY_NUMBER_SOURCE_DEFAULT >
+     *     EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG
+     *
+     */
+    private int getDisplayPriorityScore() {
+        int score = 0;
+        if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING)) {
+            score += 1 << 4;
+        }
+        if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_SIM)) {
+            score += 1 << 3;
+        }
+        // TODO add a score if the number comes from Google's emergency number database
+        if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_DEFAULT)) {
+            score += 1 << 1;
+        }
+        if (this.isFromSources(EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG)) {
+            score += 1 << 0;
+        }
+        return score;
+    }
+
+    /**
+     * Compare the display priority for this emergency number and the supplied emergency number.
+     *
+     * @param emergencyNumber the supplied emergency number
+     * @return a negative value if the supplied emergency number has a lower display priority;
+     *         a positive value if the supplied emergency number has a higher display priority;
+     *         0 if both have equal display priority.
+     */
+    @Override
+    public int compareTo(EmergencyNumber emergencyNumber) {
+        if (this.getDisplayPriorityScore()
+                > emergencyNumber.getDisplayPriorityScore()) {
+            return -1;
+        } else if (this.getDisplayPriorityScore()
+                < emergencyNumber.getDisplayPriorityScore()) {
+            return 1;
+        } else {
+            /**
+             * TODO if both numbers have the same display priority score, the number matches the
+             * Google's emergency number database has a higher display priority.
+             */
+            return 0;
+        }
+    }
+
     public static final Parcelable.Creator<EmergencyNumber> CREATOR =
             new Parcelable.Creator<EmergencyNumber>() {
         @Override
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 9730ebc..eda8e77 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -44,10 +45,6 @@
 
     private static final boolean DBG = false;
 
-    // When set to true this flag will treat all apps that fail the device identifier check as
-    // though they are targeting pre-Q and return dummy data instead of throwing a SecurityException
-    private static final boolean RELAX_DEVICE_IDENTIFIER_CHECK = true;
-
     private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
             ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
 
@@ -280,23 +277,29 @@
      */
     private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
             int uid, String callingPackage, String message) {
-        // if the device identifier check is relaxed then just return false to return dummy data to
-        // the caller instead of throwing a SecurityException for apps targeting Q+.
-        if (RELAX_DEVICE_IDENTIFIER_CHECK) {
-            Log.wtf(LOG_TAG,
-                    "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
-            return false;
+        Log.wtf(LOG_TAG,
+                "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
+        // if the device identifier check is relaxed then revert to the READ_PHONE_STATE permission
+        // check that was previously required to access device identifiers.
+        boolean relaxDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 0;
+        if (relaxDeviceIdentifierCheck) {
+            return checkReadPhoneState(context, subId, pid, uid, callingPackage, message);
         } else {
+            boolean targetQBehaviorDisabled = Settings.Global.getInt(context.getContentResolver(),
+                    Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED, 0) == 0;
             if (callingPackage != null) {
                 try {
-                    // if the target SDK is pre-Q then check if the calling package would have
-                    // previously had access to device identifiers.
+                    // if the target SDK is pre-Q or the target Q behavior is disabled then check if
+                    // the calling package would have previously had access to device identifiers.
                     ApplicationInfo callingPackageInfo =
                             context.getPackageManager().getApplicationInfo(
                                     callingPackage, 0);
-                    if (callingPackageInfo != null
-                            && callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
-                        if (context.checkPermission(android.Manifest.permission.READ_PHONE_STATE,
+                    if (callingPackageInfo != null && (
+                            callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q
+                                    || targetQBehaviorDisabled)) {
+                        if (context.checkPermission(
+                                android.Manifest.permission.READ_PHONE_STATE,
                                 pid,
                                 uid) == PackageManager.PERMISSION_GRANTED) {
                             return false;
@@ -312,8 +315,8 @@
                     // default to throwing the SecurityException.
                 }
             }
-            throw new SecurityException(message + ": The user " + uid + " does not have the "
-                    + "READ_PRIVILEGED_PHONE_STATE permission to access the device identifiers");
+            throw new SecurityException(message + ": The user " + uid
+                    + " does not meet the requirements to access device identifiers.");
         }
     }
 
diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py
new file mode 100755
index 0000000..48c0755
--- /dev/null
+++ b/tools/hiddenapi/merge_csv.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+#
+# 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.
+"""
+Merge mutliple CSV files, possibly with different columns, writing to stdout.
+"""
+
+import csv
+import sys
+
+csv_readers = [
+    csv.DictReader(open(csv_file, 'rb'), delimiter=',', quotechar='|')
+    for csv_file in sys.argv[1:]
+]
+
+# Build union of all columns from source files:
+headers = set()
+for reader in csv_readers:
+  headers = headers.union(reader.fieldnames)
+
+# Concatenate all files to output:
+out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', fieldnames = sorted(headers))
+out.writeheader()
+for reader in csv_readers:
+  for row in reader:
+    out.writerow(row)
+
+