Merge "Allow recents animation controller to control input consumer lifecycle"
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/PREUPLOAD.cfg b/PREUPLOAD.cfg
index ff40f75..5c21221 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,6 +5,7 @@
                       packages/PrintRecommendationService/
                       packages/PrintSpooler/
                       packages/PackageInstaller/
+                      packages/SystemUI/
                       services/print/
                       services/usb/
                       telephony/
diff --git a/api/current.txt b/api/current.txt
index 71793c0..bb4c98d5 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -29722,6 +29722,65 @@
     field public static final int EGL_WINDOW_BIT = 4; // 0x4
   }
 
+  public class EGL15 {
+    ctor public EGL15();
+    method public static int eglClientWaitSync(android.opengl.EGLDisplay, android.opengl.EGLSync, int, long);
+    method public static android.opengl.EGLSurface eglCreatePlatformPixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.nio.Buffer, long[], int);
+    method public static android.opengl.EGLSurface eglCreatePlatformWindowSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.nio.Buffer, long[], int);
+    method public static android.opengl.EGLSync eglCreateSync(android.opengl.EGLDisplay, int, long[], int);
+    method public static boolean eglDestroySync(android.opengl.EGLDisplay, android.opengl.EGLSync);
+    method public static android.opengl.EGLDisplay eglGetPlatformDisplay(int, long, long[], int);
+    method public static boolean eglGetSyncAttrib(android.opengl.EGLDisplay, android.opengl.EGLSync, int, long[], int);
+    method public static boolean eglWaitSync(android.opengl.EGLDisplay, android.opengl.EGLSync, int);
+    field public static final int EGL_CL_EVENT_HANDLE = 12444; // 0x309c
+    field public static final int EGL_CONDITION_SATISFIED = 12534; // 0x30f6
+    field public static final int EGL_CONTEXT_MAJOR_VERSION = 12440; // 0x3098
+    field public static final int EGL_CONTEXT_MINOR_VERSION = 12539; // 0x30fb
+    field public static final int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT = 2; // 0x2
+    field public static final int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 1; // 0x1
+    field public static final int EGL_CONTEXT_OPENGL_DEBUG = 12720; // 0x31b0
+    field public static final int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE = 12721; // 0x31b1
+    field public static final int EGL_CONTEXT_OPENGL_PROFILE_MASK = 12541; // 0x30fd
+    field public static final int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 12733; // 0x31bd
+    field public static final int EGL_CONTEXT_OPENGL_ROBUST_ACCESS = 12722; // 0x31b2
+    field public static final long EGL_FOREVER = -1L; // 0xffffffffffffffffL
+    field public static final int EGL_GL_COLORSPACE = 12445; // 0x309d
+    field public static final int EGL_GL_COLORSPACE_LINEAR = 12426; // 0x308a
+    field public static final int EGL_GL_COLORSPACE_SRGB = 12425; // 0x3089
+    field public static final int EGL_GL_RENDERBUFFER = 12473; // 0x30b9
+    field public static final int EGL_GL_TEXTURE_2D = 12465; // 0x30b1
+    field public static final int EGL_GL_TEXTURE_3D = 12466; // 0x30b2
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 12468; // 0x30b4
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 12470; // 0x30b6
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 12472; // 0x30b8
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X = 12467; // 0x30b3
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 12469; // 0x30b5
+    field public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 12471; // 0x30b7
+    field public static final int EGL_GL_TEXTURE_LEVEL = 12476; // 0x30bc
+    field public static final int EGL_GL_TEXTURE_ZOFFSET = 12477; // 0x30bd
+    field public static final int EGL_IMAGE_PRESERVED = 12498; // 0x30d2
+    field public static final int EGL_LOSE_CONTEXT_ON_RESET = 12735; // 0x31bf
+    field public static final android.opengl.EGLContext EGL_NO_CONTEXT;
+    field public static final android.opengl.EGLDisplay EGL_NO_DISPLAY;
+    field public static final android.opengl.EGLImage EGL_NO_IMAGE;
+    field public static final int EGL_NO_RESET_NOTIFICATION = 12734; // 0x31be
+    field public static final android.opengl.EGLSurface EGL_NO_SURFACE;
+    field public static final android.opengl.EGLSync EGL_NO_SYNC;
+    field public static final int EGL_OPENGL_ES3_BIT = 64; // 0x40
+    field public static final int EGL_PLATFORM_ANDROID_KHR = 12609; // 0x3141
+    field public static final int EGL_SIGNALED = 12530; // 0x30f2
+    field public static final int EGL_SYNC_CL_EVENT = 12542; // 0x30fe
+    field public static final int EGL_SYNC_CL_EVENT_COMPLETE = 12543; // 0x30ff
+    field public static final int EGL_SYNC_CONDITION = 12536; // 0x30f8
+    field public static final int EGL_SYNC_FENCE = 12537; // 0x30f9
+    field public static final int EGL_SYNC_FLUSH_COMMANDS_BIT = 1; // 0x1
+    field public static final int EGL_SYNC_PRIOR_COMMANDS_COMPLETE = 12528; // 0x30f0
+    field public static final int EGL_SYNC_STATUS = 12529; // 0x30f1
+    field public static final int EGL_SYNC_TYPE = 12535; // 0x30f7
+    field public static final int EGL_TIMEOUT_EXPIRED = 12533; // 0x30f5
+    field public static final int EGL_UNSIGNALED = 12531; // 0x30f3
+  }
+
   public class EGLConfig extends android.opengl.EGLObjectHandle {
   }
 
@@ -29741,6 +29800,9 @@
     field public static final int EGL_RECORDABLE_ANDROID = 12610; // 0x3142
   }
 
+  public class EGLImage extends android.opengl.EGLObjectHandle {
+  }
+
   public abstract class EGLObjectHandle {
     ctor protected deprecated EGLObjectHandle(int);
     ctor protected EGLObjectHandle(long);
@@ -29751,6 +29813,9 @@
   public class EGLSurface extends android.opengl.EGLObjectHandle {
   }
 
+  public class EGLSync extends android.opengl.EGLObjectHandle {
+  }
+
   public class ETC1 {
     ctor public ETC1();
     method public static void decodeBlock(java.nio.Buffer, java.nio.Buffer);
@@ -43041,9 +43106,8 @@
     method public static int getDefaultSmsSubscriptionId();
     method public static int getDefaultSubscriptionId();
     method public static int getDefaultVoiceSubscriptionId();
-    method public static int getSlotIndex(int);
-    method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(int);
+    method public static int getSlotIndex(int);
     method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isActiveSubscriptionId(int);
@@ -43439,7 +43503,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();
@@ -52310,6 +52375,7 @@
     field public static final int ERROR_UNSAFE_RESOURCE = -16; // 0xfffffff0
     field public static final int ERROR_UNSUPPORTED_AUTH_SCHEME = -3; // 0xfffffffd
     field public static final int ERROR_UNSUPPORTED_SCHEME = -10; // 0xfffffff6
+    field public static final int SAFE_BROWSING_THREAT_BILLING = 4; // 0x4
     field public static final int SAFE_BROWSING_THREAT_MALWARE = 1; // 0x1
     field public static final int SAFE_BROWSING_THREAT_PHISHING = 2; // 0x2
     field public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0; // 0x0
diff --git a/api/system-current.txt b/api/system-current.txt
index 87a44ce..580a760 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
@@ -5952,11 +5946,13 @@
   }
 
   public final class ImsExternalCallState implements android.os.Parcelable {
+    ctor public ImsExternalCallState(java.lang.String, android.net.Uri, android.net.Uri, boolean, int, int, boolean);
     method public int describeContents();
     method public android.net.Uri getAddress();
     method public int getCallId();
     method public int getCallState();
     method public int getCallType();
+    method public android.net.Uri getLocalAddress();
     method public boolean isCallHeld();
     method public boolean isCallPullable();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index c396cd1..5818f5d 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 \
@@ -217,6 +218,7 @@
     tests/metrics/metrics_test_helper.cpp \
     tests/statsd_test_util.cpp \
     tests/e2e/WakelockDuration_e2e_test.cpp \
+    tests/e2e/MetricActivation_e2e_test.cpp \
     tests/e2e/MetricConditionLink_e2e_test.cpp \
     tests/e2e/Alarm_e2e_test.cpp \
     tests/e2e/Attribution_e2e_test.cpp \
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 6a9e8a1..3e8b9b8 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);
 
@@ -219,6 +219,7 @@
 
     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
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/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index df08181..f87849e 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -64,8 +64,54 @@
         onMatchedLogEventInternalLocked(
                 matcherIndex, metricKey, conditionKey, condition, event);
     }
+}
 
- }
+bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
+    bool isActive = mEventActivationMap.empty();
+    for (auto& it : mEventActivationMap) {
+        if (it.second.state == ActivationState::kActive &&
+            elapsedTimestampNs > it.second.ttl_ns + it.second.activation_ns) {
+            it.second.state = ActivationState::kNotActive;
+        }
+        if (it.second.state == ActivationState::kActive) {
+            isActive = true;
+        }
+    }
+    return isActive;
+}
+
+void MetricProducer::flushIfExpire(int64_t elapsedTimestampNs) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (!mIsActive) {
+        return;
+    }
+    mIsActive = evaluateActiveStateLocked(elapsedTimestampNs);
+    if (!mIsActive) {
+        flushLocked(elapsedTimestampNs);
+    }
+}
+
+void MetricProducer::addActivation(int activationTrackerIndex, int64_t ttl_seconds) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    // When a metric producer does not depend on any activation, its mIsActive is true.
+    // Therefor, if this is the 1st activation, mIsActive will turn to false. Otherwise it does not
+    // change.
+    if  (mEventActivationMap.empty()) {
+        mIsActive = false;
+    }
+    mEventActivationMap[activationTrackerIndex].ttl_ns = ttl_seconds * NS_PER_SEC;
+}
+
+void MetricProducer::activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs) {
+    auto it = mEventActivationMap.find(activationTrackerIndex);
+    if (it == mEventActivationMap.end()) {
+        return;
+    }
+    it->second.activation_ns = elapsedTimestampNs;
+    it->second.state = ActivationState::kActive;
+    mIsActive = true;
+}
+
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 6fe4bfb..b21fd50 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -34,6 +34,17 @@
 namespace os {
 namespace statsd {
 
+// If the metric has no activation requirement, it will be active once the metric producer is
+// created.
+// If the metric needs to be activated by atoms, the metric producer will start
+// with kNotActive state, turn to kActive when the activation event arrives, become kNotActive
+// when it reaches the duration limit (timebomb). If the activation event arrives again before
+// or after it expires, the event producer will be re-activated and ttl will be reset.
+enum ActivationState {
+    kNotActive = 0,
+    kActive = 1,
+};
+
 // A MetricProducer is responsible for compute one single metrics, creating stats log report, and
 // writing the report to dropbox. MetricProducers should respond to package changes as required in
 // PackageInfoListener, but if none of the metrics are slicing by package name, then the update can
@@ -54,7 +65,8 @@
           mContainANYPositionInDimensionsInWhat(false),
           mSliceByPositionALL(false),
           mSameConditionDimensionsInTracker(false),
-          mHasLinksToAllConditionDimensionsInTracker(false) {
+          mHasLinksToAllConditionDimensionsInTracker(false),
+          mIsActive(true) {
     }
 
     virtual ~MetricProducer(){};
@@ -93,17 +105,23 @@
     // Consume the parsed stats log entry that already matched the "what" of the metric.
     void onMatchedLogEvent(const size_t matcherIndex, const LogEvent& event) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onMatchedLogEventLocked(matcherIndex, event);
+        if (mIsActive) {
+            onMatchedLogEventLocked(matcherIndex, event);
+        }
     }
 
     void onConditionChanged(const bool condition, const int64_t eventTime) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onConditionChangedLocked(condition, eventTime);
+        if (mIsActive) {
+            onConditionChangedLocked(condition, eventTime);
+        }
     }
 
     void onSlicedConditionMayChange(bool overallCondition, const int64_t eventTime) {
         std::lock_guard<std::mutex> lock(mMutex);
-        onSlicedConditionMayChangeLocked(overallCondition, eventTime);
+        if (mIsActive) {
+            onSlicedConditionMayChangeLocked(overallCondition, eventTime);
+        }
     }
 
     bool isConditionSliced() const {
@@ -177,6 +195,15 @@
         return mCurrentBucketNum;
     }
 
+    void activate(int activationTrackerIndex, int64_t elapsedTimestampNs) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        activateLocked(activationTrackerIndex, elapsedTimestampNs);
+    }
+
+    void addActivation(int activationTrackerIndex, int64_t ttl_seconds);
+
+    void flushIfExpire(int64_t elapsedTimestampNs);
+
 protected:
     virtual void onConditionChangedLocked(const bool condition, const int64_t eventTime) = 0;
     virtual void onSlicedConditionMayChangeLocked(bool overallCondition,
@@ -189,6 +216,10 @@
     virtual size_t byteSizeLocked() const = 0;
     virtual void dumpStatesLocked(FILE* out, bool verbose) const = 0;
 
+    bool evaluateActiveStateLocked(int64_t elapsedTimestampNs);
+
+    void activateLocked(int activationTrackerIndex, int64_t elapsedTimestampNs);
+
     /**
      * Flushes the current bucket if the eventTime is after the current bucket's end time. This will
        also flush the current partial bucket in memory.
@@ -198,9 +229,9 @@
     /**
      * Flushes all the data including the current partial bucket.
      */
-    virtual void flushLocked(const int64_t& eventTime) {
-        flushIfNeededLocked(eventTime);
-        flushCurrentBucketLocked(eventTime);
+    virtual void flushLocked(const int64_t& eventTimeNs) {
+        flushIfNeededLocked(eventTimeNs);
+        flushCurrentBucketLocked(eventTimeNs);
     };
 
     /**
@@ -295,6 +326,21 @@
     virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event);
 
     mutable std::mutex mMutex;
+
+    struct Activation {
+        Activation() : ttl_ns(0), activation_ns(0), state(ActivationState::kNotActive)  {}
+
+        int64_t ttl_ns;
+        int64_t activation_ns;
+        ActivationState state;
+    };
+    // When the metric producer has multiple activations, these activations are ORed to determine
+    // whether the metric producer is ready to generate metrics.
+    std::unordered_map<int, Activation> mEventActivationMap;
+
+    bool mIsActive;
+
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 0e5ef4d..f85ba1f 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -73,7 +73,8 @@
             key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
             timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
             mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
-            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap, mNoReportMetricIds);
+            mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
+            mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
 
     mHashStringsInReport = config.hash_strings_in_metric_report();
 
@@ -298,7 +299,12 @@
     }
 
     int tagId = event.GetTagId();
-    int64_t eventTime = event.GetElapsedTimestampNs();
+    int64_t eventTimeNs = event.GetElapsedTimestampNs();
+
+    for (int metric : mMetricIndexesWithActivation) {
+        mAllMetricProducers[metric]->flushIfExpire(eventTimeNs);
+    }
+
     if (mTagIds.find(tagId) == mTagIds.end()) {
         // not interesting...
         return;
@@ -310,6 +316,14 @@
         matcher->onLogEvent(event, mAllAtomMatchers, matcherCache);
     }
 
+    for (const auto& it : mActivationAtomTrackerToMetricMap) {
+        if (matcherCache[it.first] == MatchingState::kMatched) {
+            for (int metricIndex : it.second) {
+                mAllMetricProducers[metricIndex]->activate(it.first, eventTimeNs);
+            }
+        }
+    }
+
     // A bitmap to see which ConditionTracker needs to be re-evaluated.
     vector<bool> conditionToBeEvaluated(mAllConditionTrackers.size(), false);
 
@@ -347,13 +361,13 @@
                 // Push the new condition to it directly.
                 if (!mAllMetricProducers[metricIndex]->isConditionSliced()) {
                     mAllMetricProducers[metricIndex]->onConditionChanged(conditionCache[i],
-                                                                         eventTime);
+                                                                         eventTimeNs);
                     // metric cares about sliced conditions, and it may have changed. Send
                     // notification, and the metric can query the sliced conditions that are
                     // interesting to it.
                 } else {
                     mAllMetricProducers[metricIndex]->onSlicedConditionMayChange(conditionCache[i],
-                                                                                 eventTime);
+                                                                                 eventTimeNs);
                 }
             }
         }
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index dfbb69f..649222ff 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -195,6 +195,11 @@
     // maps from ConditionTracker to MetricProducer
     std::unordered_map<int, std::vector<int>> mConditionToMetricMap;
 
+    // maps from life span triggering event to MetricProducers.
+    std::unordered_map<int, std::vector<int>> mActivationAtomTrackerToMetricMap;
+
+    std::vector<int> mMetricIndexesWithActivation;
+
     void initLogSourceWhiteList();
 
     // The metrics that don't need to be uploaded or even reported.
@@ -207,7 +212,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);
@@ -230,6 +235,7 @@
 
     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
+    FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 75d6df9..136ba07 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);
     }
@@ -682,6 +685,44 @@
     return true;
 }
 
+bool initMetricActivations(const ConfigKey& key, const StatsdConfig& config,
+                           const int64_t currentTimeNs,
+                           const unordered_map<int64_t, int> &logEventTrackerMap,
+                           const unordered_map<int64_t, int> &metricProducerMap,
+                           vector<sp<MetricProducer>>& allMetricProducers,
+                           unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+                           vector<int>& metricsWithActivation) {
+    for (int i = 0; i < config.metric_activation_size(); ++i) {
+        const MetricActivation& metric_activation = config.metric_activation(i);
+        auto itr = metricProducerMap.find(metric_activation.metric_id());
+        if (itr == metricProducerMap.end()) {
+            ALOGE("Metric id not found in metric activation: %lld",
+                (long long)metric_activation.metric_id());
+            return false;
+        }
+        const int metricTrackerIndex = itr->second;
+        if (metricTrackerIndex < 0 || metricTrackerIndex >= (int)allMetricProducers.size()) {
+            ALOGE("Invalid metric tracker index.");
+            return false;
+        }
+        metricsWithActivation.push_back(metricTrackerIndex);
+        for (int j = 0; j < metric_activation.event_activation_size(); ++j) {
+            const EventActivation& activation = metric_activation.event_activation(j);
+            auto logTrackerIt = logEventTrackerMap.find(activation.atom_matcher_id());
+            if (logTrackerIt == logEventTrackerMap.end()) {
+                ALOGE("Atom matcher not found for event activation.");
+                return false;
+            }
+            const int atomMatcherIndex = logTrackerIt->second;
+            activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(
+                metricTrackerIndex);
+            allMetricProducers[metricTrackerIndex]->addActivation(
+                atomMatcherIndex, activation.ttl_seconds());
+        }
+    }
+    return true;
+}
+
 bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
                       const sp<StatsPullerManager>& pullerManager,
                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -695,6 +736,8 @@
                       unordered_map<int, std::vector<int>>& conditionToMetricMap,
                       unordered_map<int, std::vector<int>>& trackerToMetricMap,
                       unordered_map<int, std::vector<int>>& trackerToConditionMap,
+                      unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
+                      vector<int>& metricsWithActivation,
                       std::set<int64_t>& noReportMetricIds) {
     unordered_map<int64_t, int> logTrackerMap;
     unordered_map<int64_t, int> conditionTrackerMap;
@@ -729,6 +772,11 @@
         ALOGE("initAlarms failed");
         return false;
     }
+    if (!initMetricActivations(key, config, currentTimeNs, logTrackerMap, metricProducerMap,
+            allMetricProducers, activationAtomTrackerToMetricMap, metricsWithActivation)) {
+        ALOGE("initMetricActivations failed");
+        return false;
+    }
 
     return true;
 }
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h
index c660149..9ffceda 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/metrics_manager_util.h
@@ -108,6 +108,8 @@
                       std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
                       std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
                       std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
+                      unordered_map<int, std::vector<int>>& lifeSpanEventTrackerToMetricMap,
+                      vector<int>& metricsWithLifeSpan,
                       std::set<int64_t>& noReportMetricIds);
 
 bool isStateTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys);
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d19e247..d5f81a59 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -347,6 +347,17 @@
   optional float probability_of_informing = 7 [default = 1.1];
 }
 
+message EventActivation {
+  optional int64 atom_matcher_id = 1;
+  optional int64 ttl_seconds = 2;
+}
+
+message MetricActivation {
+  optional int64 metric_id = 1;
+
+  repeated EventActivation event_activation = 2;
+}
+
 message StatsdConfig {
   optional int64 id = 1;
 
@@ -384,6 +395,8 @@
 
   optional bool hash_strings_in_metric_report = 16 [default = true];
 
+  repeated MetricActivation metric_activation = 17;
+
   // Field number 1000 is reserved for later use.
   reserved 1000;
 }
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 8fbb58a..f8184d8 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -282,13 +282,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                  periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                  allAtomMatchers, allConditionTrackers, allMetricProducers,
                                  allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                 trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                 trackerToMetricMap, trackerToConditionMap,
+                                 lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                 noReportMetricIds));
     EXPECT_EQ(1u, allMetricProducers.size());
     EXPECT_EQ(1u, allAnomalyTrackers.size());
     EXPECT_EQ(1u, noReportMetricIds.size());
@@ -309,13 +313,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
@@ -333,13 +341,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestMissingMatchers) {
@@ -357,12 +369,16 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestMissingPredicate) {
@@ -380,12 +396,16 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, TestCirclePredicateDependency) {
@@ -403,13 +423,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
@@ -427,13 +451,17 @@
     unordered_map<int, std::vector<int>> conditionToMetricMap;
     unordered_map<int, std::vector<int>> trackerToMetricMap;
     unordered_map<int, std::vector<int>> trackerToConditionMap;
+    unordered_map<int, std::vector<int>> lifeSpanEventTrackerToMetricMap;
+    vector<int> metricsWithLifeSpan;
     std::set<int64_t> noReportMetricIds;
 
     EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
                                   periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
                                   allAtomMatchers, allConditionTrackers, allMetricProducers,
                                   allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
-                                  trackerToMetricMap, trackerToConditionMap, noReportMetricIds));
+                                  trackerToMetricMap, trackerToConditionMap,
+                                  lifeSpanEventTrackerToMetricMap, metricsWithLifeSpan,
+                                  noReportMetricIds));
 }
 
 #else
diff --git a/cmds/statsd/tests/e2e/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/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
new file mode 100644
index 0000000..0f13a4a
--- /dev/null
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -0,0 +1,242 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <gtest/gtest.h>
+
+#include "src/StatsLogProcessor.h"
+#include "src/stats_log_util.h"
+#include "tests/statsd_test_util.h"
+
+#include <vector>
+
+namespace android {
+namespace os {
+namespace statsd {
+
+#ifdef __ANDROID__
+
+namespace {
+
+StatsdConfig CreateStatsdConfig() {
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+    auto crashMatcher = CreateProcessCrashAtomMatcher();
+    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+    auto saverModeMatcher = CreateBatterySaverModeStartAtomMatcher();
+
+    *config.add_atom_matcher() = saverModeMatcher;
+    *config.add_atom_matcher() = crashMatcher;
+    *config.add_atom_matcher() = screenOnMatcher;
+
+    int64_t metricId = 123456;
+    auto countMetric = config.add_count_metric();
+    countMetric->set_id(metricId);
+    countMetric->set_what(crashMatcher.id());
+    countMetric->set_bucket(FIVE_MINUTES);
+    countMetric->mutable_dimensions_in_what()->set_field(
+        android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+    countMetric->mutable_dimensions_in_what()->add_child()->set_field(1);  // uid field
+
+    auto metric_activation1 = config.add_metric_activation();
+    metric_activation1->set_metric_id(metricId);
+    auto event_activation1 = metric_activation1->add_event_activation();
+    event_activation1->set_atom_matcher_id(saverModeMatcher.id());
+    event_activation1->set_ttl_seconds(60 * 6);  // 6 minutes
+    auto event_activation2 = metric_activation1->add_event_activation();
+    event_activation2->set_atom_matcher_id(screenOnMatcher.id());
+    event_activation2->set_ttl_seconds(60 * 2);  // 2 minutes
+
+    return config;
+}
+
+}  // namespace
+
+TEST(MetricActivationE2eTest, TestCountMetric) {
+    auto config = CreateStatsdConfig();
+
+    int64_t bucketStartTimeNs = 10000000000;
+    int64_t bucketSizeNs =
+        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+
+    ConfigKey cfgKey;
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+    sp<MetricProducer> metricProducer =
+        processor->mMetricsManagers.begin()->second->mAllMetricProducers[0];
+    auto& eventActivationMap = metricProducer->mEventActivationMap;
+
+    EXPECT_FALSE(metricProducer->mIsActive);
+    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+    // triggered by screen on event (tracker index 2).
+    EXPECT_EQ(eventActivationMap.size(), 2u);
+    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    std::unique_ptr<LogEvent> event;
+
+    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+    processor->OnLogEvent(event.get());
+    EXPECT_FALSE(metricProducer->mIsActive);
+
+    // Activated by battery save mode.
+    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, 0);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // First processed event.
+    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+    processor->OnLogEvent(event.get());
+
+    // Activated by screen on event.
+    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + 20);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // 2nd processed event.
+    // The activation by screen_on event expires, but the one by battery save mode is still active.
+    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // 3rd processed event.
+    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+    processor->OnLogEvent(event.get());
+
+    // All activations expired.
+    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+    processor->OnLogEvent(event.get());
+    EXPECT_FALSE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + 20);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    // Re-activate.
+    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+    processor->OnLogEvent(event.get());
+    EXPECT_TRUE(metricProducer->mIsActive);
+    EXPECT_EQ(eventActivationMap[0].state, ActivationState::kNotActive);
+    EXPECT_EQ(eventActivationMap[0].activation_ns, bucketStartTimeNs + 10);
+    EXPECT_EQ(eventActivationMap[0].ttl_ns, 60 * 6 * NS_PER_SEC);
+    EXPECT_EQ(eventActivationMap[2].state, ActivationState::kActive);
+    EXPECT_EQ(eventActivationMap[2].activation_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+    EXPECT_EQ(eventActivationMap[2].ttl_ns, 60 * 2 * NS_PER_SEC);
+
+    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+    processor->OnLogEvent(event.get());
+
+    ConfigMetricsReportList reports;
+    vector<uint8_t> buffer;
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, ADB_DUMP,
+                            &buffer);
+    EXPECT_TRUE(buffer.size() > 0);
+    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+    backfillDimensionPath(&reports);
+    backfillStartEndTimestamp(&reports);
+    EXPECT_EQ(1, reports.reports_size());
+    EXPECT_EQ(1, reports.reports(0).metrics_size());
+    EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
+
+    StatsLogReport::CountMetricDataWrapper countMetrics;
+    sortMetricDataByDimensionsValue(
+            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+    EXPECT_EQ(4, countMetrics.data_size());
+
+    auto data = countMetrics.data(0);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(1);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(2);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    // Partial bucket as metric is deactivated.
+    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+    data = countMetrics.data(3);
+    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+    EXPECT_EQ(1 /* uid field */,
+              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(1, data.bucket_info(0).count());
+    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+              data.bucket_info(0).start_bucket_elapsed_nanos());
+    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+              data.bucket_info(0).end_bucket_elapsed_nanos());
+
+}
+
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/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/config/preloaded-classes b/config/preloaded-classes
index 56ca98f..1a8a32e 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -2354,6 +2354,7 @@
 android.nfc.NfcAdapter$CreateNdefMessageCallback
 android.nfc.NfcManager
 android.opengl.EGL14
+android.opengl.EGL15
 android.opengl.EGLConfig
 android.opengl.EGLContext
 android.opengl.EGLDisplay
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index aca80b4..3cc5e37 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4678,7 +4678,7 @@
         if (decor != null) {
             decor.cancelPendingInputEvents();
         }
-        if (options != null && !isTopOfTask()) {
+        if (options != null) {
             mActivityTransitionState.startExitOutTransition(this, options);
         }
     }
@@ -4882,6 +4882,7 @@
             Bundle options)
             throws IntentSender.SendIntentException {
         try {
+            options = transferSpringboardActivityOptions(options);
             String resolvedType = null;
             if (fillInIntent != null) {
                 fillInIntent.migrateExtraStreamToClipData();
@@ -4898,6 +4899,12 @@
                 throw new IntentSender.SendIntentException();
             }
             Instrumentation.checkStartActivityResult(result, null);
+
+            if (options != null) {
+                // Only when the options are not null, as the intent can point to something other
+                // than an Activity.
+                cancelInputsAndStartExitTransition(options);
+            }
         } catch (RemoteException e) {
         }
         if (requestCode >= 0) {
@@ -6471,7 +6478,7 @@
      *
      * @return true if this is the topmost, non-finishing activity in its task.
      */
-    private boolean isTopOfTask() {
+    final boolean isTopOfTask() {
         if (mToken == null || mWindow == null) {
             return false;
         }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 7ae2ded..d00650d 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -244,4 +244,10 @@
     public abstract void updateOomLevelsForDisplay(int displayId);
     public abstract boolean isActivityStartsLoggingEnabled();
     public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing);
+
+    /** Input dispatch timeout to a window, start the ANR process. */
+    public abstract long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason);
+    public abstract boolean inputDispatchingTimedOut(Object proc, String activityShortComponentName,
+            ApplicationInfo aInfo, String parentShortComponentName, Object parentProc,
+            boolean aboveSystem, String reason);
 }
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3c9a2d4..94b42ff 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -195,6 +195,13 @@
     private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId";
 
     /**
+     * See {@link #setPendingIntentLaunchFlags(int)}
+     * @hide
+     */
+    private static final String KEY_PENDING_INTENT_LAUNCH_FLAGS =
+            "android.activity.pendingIntentLaunchFlags";
+
+    /**
      * See {@link #setTaskOverlay}.
      * @hide
      */
@@ -309,6 +316,7 @@
     @WindowConfiguration.ActivityType
     private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
     private int mLaunchTaskId = -1;
+    private int mPendingIntentLaunchFlags;
     private int mSplitScreenCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
     private boolean mLockTaskMode = false;
     private boolean mDisallowEnterPictureInPictureWhileLaunching;
@@ -932,6 +940,7 @@
         mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
         mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
         mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
+        mPendingIntentLaunchFlags = opts.getInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, 0);
         mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
         mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
         mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
@@ -1233,6 +1242,22 @@
     }
 
     /**
+     * Specifies intent flags to be applied for any activity started from a PendingIntent.
+     *
+     * @hide
+     */
+    public void setPendingIntentLaunchFlags(@android.content.Intent.Flags int flags) {
+        mPendingIntentLaunchFlags = flags;
+    }
+
+    /**
+     * @hide
+     */
+    public int getPendingIntentLaunchFlags() {
+        return mPendingIntentLaunchFlags;
+    }
+
+    /**
      * Set's whether the activity launched with this option should be a task overlay. That is the
      * activity will always be the top activity of the task.  If {@param canResume} is true, then
      * the task will also not be moved to the front of the stack.
@@ -1463,6 +1488,9 @@
         if (mLaunchTaskId != -1) {
             b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
         }
+        if (mPendingIntentLaunchFlags != 0) {
+            b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);
+        }
         if (mTaskOverlay) {
             b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
         }
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 9b2bfc5..4b87a64 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -193,6 +193,13 @@
      */
     public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
 
+    /**
+     * Sent by Activity#startActivity to notify the entering activity that enter animation for
+     * back is allowed. If this message is not received, the default exit animation will run when
+     * backing out of an activity (instead of the 'reverse' shared element transition).
+     */
+    public static final int MSG_ALLOW_RETURN_TRANSITION = 108;
+
     private Window mWindow;
     final protected ArrayList<String> mAllSharedElementNames;
     final protected ArrayList<View> mSharedElements = new ArrayList<View>();
@@ -346,8 +353,6 @@
         return new ArrayList<View>(mSharedElements);
     }
 
-    public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }
-
     protected Transition setTargets(Transition transition, boolean add) {
         if (transition == null || (add &&
                 (mTransitioningViews == null || mTransitioningViews.isEmpty()))) {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index b8f5a8e..3201feb 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -35,7 +35,7 @@
  */
 class ActivityTransitionState {
 
-    private static final String ENTERING_SHARED_ELEMENTS = "android:enteringSharedElements";
+    private static final String PENDING_EXIT_SHARED_ELEMENTS = "android:pendingExitSharedElements";
 
     private static final String EXITING_MAPPED_FROM = "android:exitingMappedFrom";
 
@@ -43,9 +43,9 @@
 
     /**
      * The shared elements that the calling Activity has said that they transferred to this
-     * Activity.
+     * Activity and will be transferred back during exit animation.
      */
-    private ArrayList<String> mEnteringNames;
+    private ArrayList<String> mPendingExitNames;
 
     /**
      * The names of shared elements that were shared to the called Activity.
@@ -112,8 +112,7 @@
 
     public int addExitTransitionCoordinator(ExitTransitionCoordinator exitTransitionCoordinator) {
         if (mExitTransitionCoordinators == null) {
-            mExitTransitionCoordinators =
-                    new SparseArray<WeakReference<ExitTransitionCoordinator>>();
+            mExitTransitionCoordinators = new SparseArray<>();
         }
         WeakReference<ExitTransitionCoordinator> ref = new WeakReference(exitTransitionCoordinator);
         // clean up old references:
@@ -132,7 +131,7 @@
     public void readState(Bundle bundle) {
         if (bundle != null) {
             if (mEnterTransitionCoordinator == null || mEnterTransitionCoordinator.isReturning()) {
-                mEnteringNames = bundle.getStringArrayList(ENTERING_SHARED_ELEMENTS);
+                mPendingExitNames = bundle.getStringArrayList(PENDING_EXIT_SHARED_ELEMENTS);
             }
             if (mEnterTransitionCoordinator == null) {
                 mExitingFrom = bundle.getStringArrayList(EXITING_MAPPED_FROM);
@@ -141,9 +140,21 @@
         }
     }
 
+    /**
+     * Returns the element names to be used for exit animation. It caches the list internally so
+     * that it is preserved through activty destroy and restore.
+     */
+    private ArrayList<String> getPendingExitNames() {
+        if (mPendingExitNames == null && mEnterTransitionCoordinator != null) {
+            mPendingExitNames = mEnterTransitionCoordinator.getPendingExitSharedElementNames();
+        }
+        return mPendingExitNames;
+    }
+
     public void saveState(Bundle bundle) {
-        if (mEnteringNames != null) {
-            bundle.putStringArrayList(ENTERING_SHARED_ELEMENTS, mEnteringNames);
+        ArrayList<String> pendingExitNames = getPendingExitNames();
+        if (pendingExitNames != null) {
+            bundle.putStringArrayList(PENDING_EXIT_SHARED_ELEMENTS, pendingExitNames);
         }
         if (mExitingFrom != null) {
             bundle.putStringArrayList(EXITING_MAPPED_FROM, mExitingFrom);
@@ -226,7 +237,7 @@
             }
         } else {
             mEnterTransitionCoordinator.namedViewsReady(null, null);
-            mEnteringNames = mEnterTransitionCoordinator.getAllSharedElementNames();
+            mPendingExitNames = null;
         }
 
         mExitingFrom = null;
@@ -268,7 +279,7 @@
     }
 
     public void clear() {
-        mEnteringNames = null;
+        mPendingExitNames = null;
         mExitingFrom = null;
         mExitingTo = null;
         mExitingToView = null;
@@ -296,7 +307,8 @@
     }
 
     public boolean startExitBackTransition(final Activity activity) {
-        if (mEnteringNames == null || mCalledExitCoordinator != null) {
+        ArrayList<String> pendingExitNames = getPendingExitNames();
+        if (pendingExitNames == null || mCalledExitCoordinator != null) {
             return false;
         } else {
             if (!mHasExited) {
@@ -315,7 +327,7 @@
                 }
 
                 mReturnExitCoordinator = new ExitTransitionCoordinator(activity,
-                        activity.getWindow(), activity.mEnterTransitionListener, mEnteringNames,
+                        activity.getWindow(), activity.mEnterTransitionListener, pendingExitNames,
                         null, null, true);
                 if (enterViewsTransition != null && decor != null) {
                     enterViewsTransition.resume(decor);
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index ab847fd..bce243c 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -65,6 +65,7 @@
     private OneShotPreDrawListener mViewsReadyListener;
     private final boolean mIsCrossTask;
     private Drawable mReplacedBackground;
+    private ArrayList<String> mPendingExitNames;
 
     public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
             ArrayList<String> sharedElementNames, boolean isReturning, boolean isCrossTask) {
@@ -249,6 +250,11 @@
             case MSG_CANCEL:
                 cancel();
                 break;
+            case MSG_ALLOW_RETURN_TRANSITION:
+                if (!mIsCanceled) {
+                    mPendingExitNames = mAllSharedElementNames;
+                }
+                break;
         }
     }
 
@@ -256,6 +262,10 @@
         return mIsReturning && mResultReceiver != null;
     }
 
+    public ArrayList<String> getPendingExitSharedElementNames() {
+        return mPendingExitNames;
+    }
+
     /**
      * This is called onResume. If an Activity is resuming and the transitions
      * haven't started yet, force the views to appear. This is likely to be
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index df31da9..48a711e 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -433,6 +433,11 @@
             if (!mSharedElementNotified) {
                 mSharedElementNotified = true;
                 delayCancel();
+
+                if (!mActivity.isTopOfTask()) {
+                    mResultReceiver.send(MSG_ALLOW_RETURN_TRANSITION, null);
+                }
+
                 if (mListener == null) {
                     mResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, mSharedElementBundle);
                     notifyExitComplete();
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/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 384115b..0c56d48 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.opengl.EGL14;
 import android.os.Build;
@@ -30,6 +31,7 @@
 
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -54,6 +56,7 @@
     private static final String PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
     private static final String ANGLE_PACKAGE_NAME = "com.android.angle";
     private static final String GLES_MODE_METADATA_KEY = "com.android.angle.GLES_MODE";
+    private static final String ANGLE_RULES_FILE = "a4a_rules.json";
 
     private ClassLoader mClassLoader;
     private String mLayerPath;
@@ -250,8 +253,40 @@
 
         if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
 
+        // Pass the rules file to loader for ANGLE decisions
+        AssetManager angleAssets = null;
+        try {
+            angleAssets =
+                context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
+            return;
+        }
+
+        AssetFileDescriptor assetsFd = null;
+        try {
+            assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
+                       + "'" + ANGLE_PACKAGE_NAME + "'");
+            return;
+        }
+
+        FileDescriptor rulesFd = null;
+        long rulesOffset = 0;
+        long rulesLength = 0;
+        if (assetsFd != null) {
+            rulesFd = assetsFd.getFileDescriptor();
+            rulesOffset = assetsFd.getStartOffset();
+            rulesLength = assetsFd.getLength();
+        } else {
+            Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
+            return;
+        }
+
         // Further opt-in logic is handled in native, so pass relevant info down
-        setAngleInfo(paths, packageName, appPref, devOptIn);
+        setAngleInfo(paths, packageName, appPref, devOptIn,
+                     rulesFd, rulesOffset, rulesLength);
     }
 
     /**
@@ -391,5 +426,6 @@
     private static native void setDebugLayers(String layers);
     private static native void setDriverPath(String path);
     private static native void setAngleInfo(String path, String appPackage, String appPref,
-                                            boolean devOptIn);
+                                            boolean devOptIn, FileDescriptor rulesFd,
+                                            long rulesOffset, long rulesLength);
 }
diff --git a/core/java/android/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/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e8e4b4ab..a401c6d 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1052,13 +1052,6 @@
         mNextServedView = null;
         if (mServedView != null) {
             if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
-            if (mCurrentTextBoxAttribute != null) {
-                try {
-                    mService.finishInput(mClient);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
             mServedView = null;
             mCompletions = null;
             mServedConnecting = false;
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index bdd7a09..69d7202 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -282,19 +282,28 @@
             SAFE_BROWSING_THREAT_UNKNOWN,
             SAFE_BROWSING_THREAT_MALWARE,
             SAFE_BROWSING_THREAT_PHISHING,
-            SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE
+            SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE,
+            SAFE_BROWSING_THREAT_BILLING,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SafeBrowsingThreat {}
 
-    /** The resource was blocked for an unknown reason */
+    /** The resource was blocked for an unknown reason. */
     public static final int SAFE_BROWSING_THREAT_UNKNOWN = 0;
-    /** The resource was blocked because it contains malware */
+    /** The resource was blocked because it contains malware. */
     public static final int SAFE_BROWSING_THREAT_MALWARE = 1;
-    /** The resource was blocked because it contains deceptive content */
+    /** The resource was blocked because it contains deceptive content. */
     public static final int SAFE_BROWSING_THREAT_PHISHING = 2;
-    /** The resource was blocked because it contains unwanted software */
+    /** The resource was blocked because it contains unwanted software. */
     public static final int SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE = 3;
+    /**
+     * The resource was blocked because it may trick the user into a billing agreement.
+     *
+     * <p>This constant is only used when targetSdkVersion is greater than {@link
+     * android.os.Build.VERSION_CODES#Q}. Otherwise, {@link #SAFE_BROWSING_THREAT_UNKNOWN} is used
+     * instead.
+     */
+    public static final int SAFE_BROWSING_THREAT_BILLING = 4;
 
     /**
      * Report an error to the host application. These errors are unrecoverable
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 8f17e96..4d03123 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -370,10 +370,12 @@
                 // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
                 Context context = view.getContext();
                 ActivityOptions opts = getActivityOptions(context);
+                // The NEW_TASK flags are applied through the activity options and not as a part of
+                // the call to startIntentSender() to ensure that they are consistently applied to
+                // both mutable and immutable PendingIntents.
                 context.startIntentSender(
                         pendingIntent.getIntentSender(), fillInIntent,
-                        Intent.FLAG_ACTIVITY_NEW_TASK,
-                        Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
+                        0, 0, 0, opts.toBundle());
             } catch (IntentSender.SendIntentException e) {
                 android.util.Log.e(LOG_TAG, "Cannot send pending intent: ", e);
                 return false;
@@ -401,10 +403,15 @@
                 windowAnimationStyle.recycle();
 
                 if (enterAnimationId != 0) {
-                    return ActivityOptions.makeCustomAnimation(context, enterAnimationId, 0);
+                    final ActivityOptions opts = ActivityOptions.makeCustomAnimation(context,
+                            enterAnimationId, 0);
+                    opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    return opts;
                 }
             }
-            return ActivityOptions.makeBasic();
+            final ActivityOptions opts = ActivityOptions.makeBasic();
+            opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            return opts;
         }
     }
 
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index dceacda..34e8501 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -46,7 +46,6 @@
     // Currently there is a bug that aidl doesn't accept List<Parcelable>
     List getShortcutInputMethodsAndSubtypes();
 
-    void finishInput(in IInputMethodClient client);
     boolean showSoftInput(in IInputMethodClient client, int flags,
             in ResultReceiver resultReceiver);
     boolean hideSoftInput(in IInputMethodClient client, int flags,
diff --git a/core/java/com/google/android/collect/Lists.java b/core/java/com/google/android/collect/Lists.java
index c029bb2..3ea873b 100644
--- a/core/java/com/google/android/collect/Lists.java
+++ b/core/java/com/google/android/collect/Lists.java
@@ -16,6 +16,7 @@
 
 package com.google.android.collect;
 
+import android.annotation.UnsupportedAppUsage;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -33,6 +34,7 @@
      *
      * @return a newly-created, initially-empty {@code ArrayList}
      */
+    @UnsupportedAppUsage
     public static <E> ArrayList<E> newArrayList() {
         return new ArrayList<E>();
     }
diff --git a/core/java/com/google/android/collect/Maps.java b/core/java/com/google/android/collect/Maps.java
index fc2c9fe..6ba3320 100644
--- a/core/java/com/google/android/collect/Maps.java
+++ b/core/java/com/google/android/collect/Maps.java
@@ -16,6 +16,7 @@
 
 package com.google.android.collect;
 
+import android.annotation.UnsupportedAppUsage;
 import android.util.ArrayMap;
 
 import java.util.HashMap;
@@ -29,6 +30,7 @@
      *
      * @return a newly-created, initially-empty {@code HashMap}
      */
+    @UnsupportedAppUsage
     public static <K, V> HashMap<K, V> newHashMap() {
         return new HashMap<K, V>();
     }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index ed6445d..59c29e2 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -45,6 +45,7 @@
         "android_app_NativeActivity.cpp",
         "android_app_admin_SecurityLog.cpp",
         "android_opengl_EGL14.cpp",
+        "android_opengl_EGL15.cpp",
         "android_opengl_EGLExt.cpp",
         "android_opengl_GLES10.cpp",
         "android_opengl_GLES10Ext.cpp",
@@ -239,6 +240,7 @@
 
     shared_libs: [
         "libbpf",
+        "libnetdbpf",
         "libnetdutils",
         "libmemtrack",
         "libandroidfw",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index c05bad2..eada690 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -77,6 +77,7 @@
 extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
 extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
 extern int register_android_opengl_jni_EGL14(JNIEnv* env);
+extern int register_android_opengl_jni_EGL15(JNIEnv* env);
 extern int register_android_opengl_jni_EGLExt(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10(JNIEnv* env);
 extern int register_android_opengl_jni_GLES10Ext(JNIEnv* env);
@@ -1367,6 +1368,7 @@
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
     REG_JNI(register_com_google_android_gles_jni_GLImpl),
     REG_JNI(register_android_opengl_jni_EGL14),
+    REG_JNI(register_android_opengl_jni_EGL15),
     REG_JNI(register_android_opengl_jni_EGLExt),
     REG_JNI(register_android_opengl_jni_GLES10),
     REG_JNI(register_android_opengl_jni_GLES10Ext),
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/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
new file mode 100644
index 0000000..4a30bab
--- /dev/null
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -0,0 +1,557 @@
+/*
+** Copyright 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 GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <EGL/egl.h>
+
+#include <ui/ANativeObjectBase.h>
+
+static int initialized = 0;
+
+// classes from EGL 1.4
+static jclass egldisplayClass;
+static jclass eglsurfaceClass;
+static jclass eglconfigClass;
+static jclass eglcontextClass;
+static jclass bufferClass;
+static jclass nioAccessClass;
+
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+
+static jmethodID egldisplayGetHandleID;
+static jmethodID eglconfigGetHandleID;
+static jmethodID eglcontextGetHandleID;
+static jmethodID eglsurfaceGetHandleID;
+
+static jmethodID egldisplayConstructor;
+static jmethodID eglcontextConstructor;
+static jmethodID eglsurfaceConstructor;
+static jmethodID eglconfigConstructor;
+
+static jobject eglNoContextObject;
+static jobject eglNoDisplayObject;
+static jobject eglNoSurfaceObject;
+
+// classes from EGL 1.5
+static jclass eglimageClass;
+static jclass eglsyncClass;
+
+static jmethodID eglimageGetHandleID;
+static jmethodID eglsyncGetHandleID;
+
+static jmethodID eglimageConstructor;
+static jmethodID eglsyncConstructor;
+
+static jobject eglNoImageObject;
+static jobject eglNoSyncObject;
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    // EGL 1.4 Init
+    jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
+    eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+    jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
+    eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
+    jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
+    egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
+    jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
+    eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
+
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+
+
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
+    eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
+    eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
+    eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+
+
+    jclass eglClass = _env->FindClass("android/opengl/EGL15");
+    jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
+    _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject);
+
+    jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
+    _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject);
+
+    jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
+    _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
+
+    // EGL 1.5 init
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+
+    jclass eglimageClassLocal = _env->FindClass("android/opengl/EGLImage");
+    eglimageClass = (jclass) _env->NewGlobalRef(eglimageClassLocal);
+    jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
+    eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal);
+
+    eglimageGetHandleID = _env->GetMethodID(eglimageClass, "getNativeHandle", "()J");
+    eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
+
+    eglimageConstructor = _env->GetMethodID(eglimageClass, "<init>", "(J)V");
+    eglsyncConstructor = _env->GetMethodID(eglsyncClass, "<init>", "(J)V");
+
+    jfieldID noImageFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_IMAGE", "Landroid/opengl/EGLImage;");
+    _env->SetStaticObjectField(eglClass, noImageFieldID, eglNoImageObject);
+
+    jfieldID noSyncFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SYNC", "Landroid/opengl/EGLSync;");
+    _env->SetStaticObjectField(eglClass, noSyncFieldID, eglNoSyncObject);
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return reinterpret_cast<void*>(pointer);
+    }
+    eglimageGetHandleID = _env->GetMethodID(eglimageClass, "getNativeHandle", "()J");
+    eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
+
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+
+    return NULL;
+}
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+                       commit ? 0 : JNI_ABORT);
+}
+
+static void *
+fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) {
+    if (obj == NULL){
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Object is set to null.");
+    }
+
+    jlong handle = _env->CallLongMethod(obj, mid);
+    return reinterpret_cast<void*>(handle);
+}
+
+static jobject
+toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
+    if (cls == eglimageClass &&
+       (EGLImage)handle == EGL_NO_IMAGE) {
+           return eglNoImageObject;
+    }
+
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
+}
+
+// --------------------------------------------------------------------------
+/* EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreateSync
+  (JNIEnv *_env, jobject _this, jobject dpy, jint type, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLSync _returnValue = (EGLSync) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
+    jint _remaining;
+    EGLAttrib *attrib_list = (EGLAttrib *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLAttrib *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+
+    _returnValue = eglCreateSync(
+        (EGLDisplay)dpy_native,
+        (EGLenum)type,
+        (EGLAttrib *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsyncClass, eglsyncConstructor, _returnValue);
+}
+
+/* EGLBoolean eglDestroySync ( EGLDisplay dpy, EGLSync sync ) */
+static jboolean
+android_eglDestroySync
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject sync) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+
+    _returnValue = eglDestroySync(
+        (EGLDisplay)dpy_native,
+        (EGLSync)sync_native
+    );
+    return (jboolean)_returnValue;
+}
+
+/* EGLint eglClientWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout ) */
+static jint
+android_eglClientWaitSync
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint flags, jlong timeout) {
+    EGLint _returnValue = (EGLint) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+
+    _returnValue = eglClientWaitSync(
+        (EGLDisplay)dpy_native,
+        (EGLSync)sync_native,
+        (EGLint)flags,
+        (EGLTime)timeout
+    );
+    return (jint)_returnValue;
+}
+
+/* EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value ) */
+static jboolean
+android_eglGetSyncAttrib
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint attribute, jlongArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+    EGLAttrib *value_base = (EGLAttrib *) 0;
+    jint _remaining;
+    EGLAttrib *value = (EGLAttrib *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (EGLAttrib *)
+        _env->GetLongArrayElements(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    _returnValue = eglGetSyncAttrib(
+        (EGLDisplay)dpy_native,
+        (EGLSync)sync_native,
+        (EGLint)attribute,
+        (EGLAttrib *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleaseLongArrayElements(value_ref, (jlong*)value_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jboolean)_returnValue;
+}
+
+/* EGLDisplay eglGetPlatformDisplay ( EGLenum platform, EGLAttrib native_display, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglGetPlatformDisplay
+  (JNIEnv *_env, jobject _this, jint platform, jlong native_display, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    EGLDisplay _returnValue = (EGLDisplay) 0;
+    EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
+    jint _remaining;
+    EGLAttrib *attrib_list = (EGLAttrib *) 0;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLAttrib *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+
+    _returnValue = eglGetPlatformDisplay(
+        (EGLenum)platform,
+        (void *)native_display,
+        (EGLAttrib *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreatePlatformWindowSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_window_buf, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    jint _native_windowRemaining;
+    void *native_window = (void *) 0;
+    EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
+    jint _attrib_listRemaining;
+    EGLAttrib *attrib_list = (EGLAttrib *) 0;
+
+    if (!native_window_buf) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "native_window == null";
+        goto exit;
+    }
+    native_window = (void *)getPointer(_env, native_window_buf, (jarray*)&_array, &_native_windowRemaining, &_bufferOffset);
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLAttrib *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+
+    if (native_window == NULL) {
+        char * _native_windowBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        native_window = (void *) (_native_windowBase + _bufferOffset);
+    }
+    _returnValue = eglCreatePlatformWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (void *)native_window,
+        (EGLAttrib *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_array) {
+        releasePointer(_env, _array, native_window, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreatePlatformPixmapSurface ( EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list ) */
+static jobject
+android_eglCreatePlatformPixmapSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject native_pixmap_buf, jlongArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    jint _native_pixmapRemaining;
+    void *native_pixmap = (void *) 0;
+    EGLAttrib *attrib_list_base = (EGLAttrib *) 0;
+    jint _attrib_listRemaining;
+    EGLAttrib *attrib_list = (EGLAttrib *) 0;
+
+    if (!native_pixmap_buf) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "native_pixmap == null";
+        goto exit;
+    }
+    native_pixmap = (void *)getPointer(_env, native_pixmap_buf, (jarray*)&_array, &_native_pixmapRemaining, &_bufferOffset);
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _attrib_listRemaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLAttrib *)
+        _env->GetLongArrayElements(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+
+    if (native_pixmap == NULL) {
+        char * _native_pixmapBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        native_pixmap = (void *) (_native_pixmapBase + _bufferOffset);
+    }
+    _returnValue = eglCreatePlatformPixmapSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (void *)native_pixmap,
+        (EGLAttrib *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleaseLongArrayElements(attrib_list_ref, (jlong*)attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_array) {
+        releasePointer(_env, _array, native_pixmap, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLBoolean eglWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags ) */
+static jboolean
+android_eglWaitSync
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject sync, jint flags) {
+    EGLBoolean _returnValue = (EGLBoolean) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLSync sync_native = (EGLSync) fromEGLHandle(_env, eglsyncGetHandleID, sync);
+
+    _returnValue = eglWaitSync(
+        (EGLDisplay)dpy_native,
+        (EGLSync)sync_native,
+        (EGLint)flags
+    );
+    return (jboolean)_returnValue;
+}
+
+static const char *classPathName = "android/opengl/EGL15";
+
+static const JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"eglCreateSync", "(Landroid/opengl/EGLDisplay;I[JI)Landroid/opengl/EGLSync;", (void *) android_eglCreateSync },
+{"eglDestroySync", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;)Z", (void *) android_eglDestroySync },
+{"eglClientWaitSync", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;IJ)I", (void *) android_eglClientWaitSync },
+{"eglGetSyncAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;I[JI)Z", (void *) android_eglGetSyncAttrib },
+{"eglGetPlatformDisplay", "(IJ[JI)Landroid/opengl/EGLDisplay;", (void *) android_eglGetPlatformDisplay },
+{"eglCreatePlatformWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformWindowSurface },
+{"eglCreatePlatformPixmapSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/nio/Buffer;[JI)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePlatformPixmapSurface },
+{"eglWaitSync", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSync;I)Z", (void *) android_eglWaitSync },
+};
+
+int register_android_opengl_jni_EGL15(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 92235ad..e64da5c 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,12 +32,16 @@
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
 }
 
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn) {
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn,
+                         jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
     ScopedUtfChars pathChars(env, path);
     ScopedUtfChars appNameChars(env, appName);
     ScopedUtfChars appPrefChars(env, appPref);
+
+    int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
+
     android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
-            appPrefChars.c_str(), devOptIn);
+            appPrefChars.c_str(), devOptIn, rulesFd_native, rulesOffset, rulesLength);
 }
 
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -57,7 +61,7 @@
 const JNINativeMethod g_methods[] = {
     { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
-    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)V", reinterpret_cast<void*>(setAngleInfo_native) },
+    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
     { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
 };
diff --git a/core/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/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index c98e646..7360e9f 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -20,7 +20,6 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
@@ -239,7 +238,6 @@
     }
 
     @Test
-    @Suppress
     public void testEmojiModifier() {
         EditorState state = new EditorState();
 
@@ -256,20 +254,15 @@
         // Isolated multiple emoji modifier
         state.setByString("| U+1F3FB U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
 
         // Multiple emoji modifiers
         state.setByString("| U+1F466 U+1F3FB U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
     }
 
     @Test
-    @Suppress
     public void testMixedEdgeCases() {
         EditorState state = new EditorState();
 
@@ -318,7 +311,7 @@
         // COMBINING ENCLOSING KEYCAP + emoji modifier
         state.setByString("| '1' U+20E3 U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // Emoji modifier + COMBINING ENCLOSING KEYCAP
         state.setByString("| U+1F466 U+1F3FB U+20E3");
@@ -360,7 +353,7 @@
         // Variation selector + emoji modifier
         state.setByString("| U+2665 U+FE0F U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // Emoji modifier + variation selector
         state.setByString("| U+1F466 U+1F3FB U+FE0F");
@@ -396,7 +389,7 @@
         // Start with ZERO WIDTH JOINER + emoji modifier
         state.setByString("| U+200D U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
+        state.assertEquals("|");
 
         // ZERO WIDTH JOINER + emoji modifier
         state.setByString("| U+1F469 U+200D U+1F3FB");
@@ -418,8 +411,6 @@
         // Regional indicator symbol + emoji modifier
         state.setByString("| U+1F1FA U+1F3FB");
         forwardDelete(state, 0);
-        state.assertEquals("| U+1F3FB");
-        forwardDelete(state, 0);
         state.assertEquals("|");
 
         // Emoji modifier + regional indicator symbol
diff --git a/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/media/OWNERS b/media/OWNERS
index 1ae2a7b..0abf9ae 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -9,4 +9,4 @@
 wjia@google.com
 jaewan@google.com
 chz@google.com
-
+dwkang@google.com
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c074cce..e8c97bc 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3942,18 +3942,31 @@
     }
 
      /**
-     * Indicate Hearing Aid connection state change.
+     * Indicate Hearing Aid connection state change and eventually suppress
+     * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
      * @param device Bluetooth device connected/disconnected
      * @param state new connection state (BluetoothProfile.STATE_xxx)
+     * @param musicDevice Default get system volume for the connecting device.
+     * (either {@link android.bluetooth.BluetoothProfile.hearingaid} or
+     * {@link android.bluetooth.BluetoothProfile.HEARING_AID})
+     * @param suppressNoisyIntent if true the
+     * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
+     * @return a delay in ms that the caller should wait before broadcasting
+     * BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED intent.
      * {@hide}
      */
-    public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state) {
+    public int setBluetoothHearingAidDeviceConnectionState(
+                BluetoothDevice device, int state, boolean suppressNoisyIntent,
+                int musicDevice) {
         final IAudioService service = getService();
+        int delay = 0;
         try {
-            service.setHearingAidDeviceConnectionState(device, state);
+            delay = service.setBluetoothHearingAidDeviceConnectionState(device,
+                state, suppressNoisyIntent, musicDevice);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
+        return delay;
     }
 
      /**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 569db16..abd6411 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -151,8 +151,6 @@
     void setWiredDeviceConnectionState(int type, int state, String address, String name,
             String caller);
 
-    void setHearingAidDeviceConnectionState(in BluetoothDevice device, int state);
-
     int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
 
     void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
@@ -210,6 +208,9 @@
 
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
+    int setBluetoothHearingAidDeviceConnectionState(in BluetoothDevice device,
+            int state, boolean suppressNoisyIntent, int musicDevice);
+
     int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
             int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 6d122d7..ee12b91 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1192,15 +1192,17 @@
     public static final int SECURITY_LEVEL_HW_SECURE_ALL = 5;
 
     /**
-     * The maximum security level supported by the device. This is the default
-     * security level when a session is opened.
+     * Indicates that the maximum security level supported by the device should
+     * be used when opening a session. This is the default security level
+     * selected when a session is opened.
      * @hide
      */
     public static final int SECURITY_LEVEL_MAX = 6;
 
     /**
-     * The maximum security level supported by the device. This is the default
-     * security level when a session is opened.
+     * Returns a value that may be passed as a parameter to {@link #openSession(int)}
+     * requesting that the session be opened at the maximum security level of
+     * the device.
      */
     public static final int getMaxSecurityLevel() {
         return SECURITY_LEVEL_MAX;
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 5adbc15..71df7dc 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -682,7 +682,9 @@
             case DataSourceDesc.TYPE_CALLBACK:
                 handleDataSource(isCurrent,
                                  srcId,
-                                 dsd.getMedia2DataSource());
+                                 dsd.getMedia2DataSource(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
                 break;
 
             case DataSourceDesc.TYPE_FD:
@@ -690,7 +692,9 @@
                                  srcId,
                                  dsd.getFileDescriptor(),
                                  dsd.getFileDescriptorOffset(),
-                                 dsd.getFileDescriptorLength());
+                                 dsd.getFileDescriptorLength(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
                 break;
 
             case DataSourceDesc.TYPE_URI:
@@ -699,7 +703,9 @@
                                  dsd.getUriContext(),
                                  dsd.getUri(),
                                  dsd.getUriHeaders(),
-                                 dsd.getUriCookies());
+                                 dsd.getUriCookies(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
                 break;
 
             default:
@@ -729,62 +735,77 @@
     private void handleDataSource(
             boolean isCurrent, long srcId,
             @NonNull Context context, @NonNull Uri uri,
-            @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)
+            @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies,
+            long startPos, long endPos)
             throws IOException {
-        // The context and URI usually belong to the calling user. Get a resolver for that user
-        // and strip out the userId from the URI if present.
+        // The context and URI usually belong to the calling user. Get a resolver for that user.
         final ContentResolver resolver = context.getContentResolver();
         final String scheme = uri.getScheme();
-        final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority());
         if (ContentResolver.SCHEME_FILE.equals(scheme)) {
-            handleDataSource(isCurrent, srcId, uri.getPath(), null, null);
+            handleDataSource(isCurrent, srcId, uri.getPath(), null, null, startPos, endPos);
             return;
         }
 
-        AssetFileDescriptor afd = null;
+        final int ringToneType = RingtoneManager.getDefaultType(uri);
         try {
+            AssetFileDescriptor afd;
             // Try requested Uri locally first
-            if (ContentResolver.SCHEME_CONTENT.equals(scheme)
-                    && Settings.AUTHORITY.equals(authority)) {
+            if (ContentResolver.SCHEME_CONTENT.equals(scheme) && ringToneType != -1) {
                 afd = RingtoneManager.openDefaultRingtoneUri(context, uri);
+                if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
+                    return;
+                }
+                final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(
+                        context, ringToneType);
+                afd = resolver.openAssetFileDescriptor(actualUri, "r");
             } else {
                 afd = resolver.openAssetFileDescriptor(uri, "r");
             }
-            if (afd != null) {
-                handleDataSource(isCurrent, srcId, afd);
+            if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
                 return;
             }
         } catch (NullPointerException | SecurityException | IOException ex) {
             Log.w(TAG, "Couldn't open " + uri + ": " + ex);
             // Fallback to media server
+        }
+        handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies, startPos, endPos);
+    }
+
+    private boolean attemptDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd,
+            long startPos, long endPos) throws IOException {
+        try {
+            if (afd.getDeclaredLength() < 0) {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        0,
+                        DataSourceDesc.LONG_MAX,
+                        startPos,
+                        endPos);
+            } else {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength(),
+                        startPos,
+                        endPos);
+            }
+            return true;
+        } catch (NullPointerException | SecurityException | IOException ex) {
+            Log.w(TAG, "Couldn't open srcId:" + srcId + ": " + ex);
+            return false;
         } finally {
             if (afd != null) {
                 afd.close();
             }
         }
-        handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies);
-    }
-
-    private void handleDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd)
-            throws IOException {
-        if (afd.getDeclaredLength() < 0) {
-            handleDataSource(isCurrent,
-                    srcId,
-                    afd.getFileDescriptor(),
-                    0,
-                    DataSourceDesc.LONG_MAX);
-        } else {
-            handleDataSource(isCurrent,
-                    srcId,
-                    afd.getFileDescriptor(),
-                    afd.getStartOffset(),
-                    afd.getDeclaredLength());
-        }
     }
 
     private void handleDataSource(
             boolean isCurrent, long srcId,
-            String path, Map<String, String> headers, List<HttpCookie> cookies)
+            String path, Map<String, String> headers, List<HttpCookie> cookies,
+            long startPos, long endPos)
             throws IOException {
         String[] keys = null;
         String[] values = null;
@@ -800,11 +821,12 @@
                 ++i;
             }
         }
-        handleDataSource(isCurrent, srcId, path, keys, values, cookies);
+        handleDataSource(isCurrent, srcId, path, keys, values, cookies, startPos, endPos);
     }
 
     private void handleDataSource(boolean isCurrent, long srcId,
-            String path, String[] keys, String[] values, List<HttpCookie> cookies)
+            String path, String[] keys, String[] values, List<HttpCookie> cookies,
+            long startPos, long endPos)
             throws IOException {
         final Uri uri = Uri.parse(path);
         final String scheme = uri.getScheme();
@@ -818,7 +840,9 @@
                 Media2HTTPService.createHTTPService(path, cookies),
                 path,
                 keys,
-                values);
+                values,
+                startPos,
+                endPos);
             return;
         }
 
@@ -826,7 +850,7 @@
         if (file.exists()) {
             FileInputStream is = new FileInputStream(file);
             FileDescriptor fd = is.getFD();
-            handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX);
+            handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX, startPos, endPos);
             is.close();
         } else {
             throw new IOException("handleDataSource failed.");
@@ -835,7 +859,8 @@
 
     private native void nativeHandleDataSourceUrl(
             boolean isCurrent, long srcId,
-            Media2HTTPService httpService, String path, String[] keys, String[] values)
+            Media2HTTPService httpService, String path, String[] keys, String[] values,
+            long startPos, long endPos)
             throws IOException;
 
     /**
@@ -849,23 +874,27 @@
      */
     private void handleDataSource(
             boolean isCurrent, long srcId,
-            FileDescriptor fd, long offset, long length) throws IOException {
-        nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length);
+            FileDescriptor fd, long offset, long length,
+            long startPos, long endPos) throws IOException {
+        nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length, startPos, endPos);
     }
 
     private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId,
-            FileDescriptor fd, long offset, long length) throws IOException;
+            FileDescriptor fd, long offset, long length,
+            long startPos, long endPos) throws IOException;
 
     /**
      * @throws IllegalStateException if it is called in an invalid state
      * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
      */
-    private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource) {
-        nativeHandleDataSourceCallback(isCurrent, srcId, dataSource);
+    private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource,
+            long startPos, long endPos) {
+        nativeHandleDataSourceCallback(isCurrent, srcId, dataSource, startPos, endPos);
     }
 
     private native void nativeHandleDataSourceCallback(
-            boolean isCurrent, long srcId, Media2DataSource dataSource);
+            boolean isCurrent, long srcId, Media2DataSource dataSource,
+            long startPos, long endPos);
 
     /**
      * @return true if there is a next data source, false otherwise.
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 352df81..61c28ed 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -283,7 +283,8 @@
 static void
 android_media_MediaPlayer2_handleDataSourceUrl(
         JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId,
-        jobject httpServiceObj, jstring path, jobjectArray keys, jobjectArray values) {
+        jobject httpServiceObj, jstring path, jobjectArray keys, jobjectArray values,
+        jlong startPos, jlong endPos) {
 
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
@@ -300,7 +301,8 @@
     if (tmp == NULL) {  // Out of memory
         return;
     }
-    ALOGV("handleDataSourceUrl: path %s, srcId %lld", tmp, (long long)srcId);
+    ALOGV("handleDataSourceUrl: path %s, srcId %lld, start %lld, end %lld",
+          tmp, (long long)srcId, (long long)startPos, (long long)endPos);
 
     if (strncmp(tmp, "content://", 10) == 0) {
         ALOGE("handleDataSourceUrl: content scheme is not supported in native code");
@@ -313,6 +315,8 @@
     dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_URL;
     dsd->mUrl = tmp;
+    dsd->mStartPositionMs = startPos;
+    dsd->mEndPositionMs = endPos;
 
     env->ReleaseStringUTFChars(path, tmp);
     tmp = NULL;
@@ -341,9 +345,9 @@
 
 static void
 android_media_MediaPlayer2_handleDataSourceFD(
-    JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId,
-    jobject fileDescriptor, jlong offset, jlong length)
-{
+        JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId,
+        jobject fileDescriptor, jlong offset, jlong length,
+        jlong startPos, jlong endPos) {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -355,8 +359,10 @@
         return;
     }
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    ALOGV("handleDataSourceFD: srcId=%lld, fd=%d (%s), offset=%lld, length=%lld",
-          (long long)srcId, fd, nameForFd(fd).c_str(), (long long)offset, (long long)length);
+    ALOGV("handleDataSourceFD: srcId=%lld, fd=%d (%s), offset=%lld, length=%lld, "
+          "start=%lld, end=%lld",
+          (long long)srcId, fd, nameForFd(fd).c_str(), (long long)offset, (long long)length,
+          (long long)startPos, (long long)endPos);
 
     struct stat sb;
     int ret = fstat(fd, &sb);
@@ -389,6 +395,8 @@
     dsd->mFD = fd;
     dsd->mFDOffset = offset;
     dsd->mFDLength = length;
+    dsd->mStartPositionMs = startPos;
+    dsd->mEndPositionMs = endPos;
 
     status_t err;
     if (isCurrent) {
@@ -402,7 +410,8 @@
 
 static void
 android_media_MediaPlayer2_handleDataSourceCallback(
-    JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId, jobject dataSource)
+    JNIEnv *env, jobject thiz, jboolean isCurrent, jlong srcId, jobject dataSource,
+    jlong startPos, jlong endPos)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
@@ -419,6 +428,8 @@
     dsd->mId = srcId;
     dsd->mType = DataSourceDesc::TYPE_CALLBACK;
     dsd->mCallbackSource = callbackDataSource;
+    dsd->mStartPositionMs = startPos;
+    dsd->mEndPositionMs = endPos;
 
     status_t err;
     if (isCurrent) {
@@ -1442,17 +1453,17 @@
     {
         "nativeHandleDataSourceUrl",
         "(ZJLandroid/media/Media2HTTPService;Ljava/lang/String;[Ljava/lang/String;"
-        "[Ljava/lang/String;)V",
+        "[Ljava/lang/String;JJ)V",
         (void *)android_media_MediaPlayer2_handleDataSourceUrl
     },
     {
         "nativeHandleDataSourceFD",
-        "(ZJLjava/io/FileDescriptor;JJ)V",
+        "(ZJLjava/io/FileDescriptor;JJJJ)V",
         (void *)android_media_MediaPlayer2_handleDataSourceFD
     },
     {
         "nativeHandleDataSourceCallback",
-        "(ZJLandroid/media/Media2DataSource;)V",
+        "(ZJLandroid/media/Media2DataSource;JJ)V",
         (void *)android_media_MediaPlayer2_handleDataSourceCallback
     },
     {"nativePlayNextDataSource", "(J)V",                        (void *)android_media_MediaPlayer2_playNextDataSource},
diff --git a/opengl/java/android/opengl/EGL15.java b/opengl/java/android/opengl/EGL15.java
new file mode 100644
index 0000000..9aae6ad
--- /dev/null
+++ b/opengl/java/android/opengl/EGL15.java
@@ -0,0 +1,149 @@
+/*
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * EGL 1.5
+ *
+ */
+public class EGL15 {
+
+    public static final int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT            = 0x00000001;
+    public static final int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT   = 0x00000002;
+    public static final int EGL_OPENGL_ES3_BIT                             = 0x00000040;
+    public static final int EGL_SYNC_FLUSH_COMMANDS_BIT                    = 0x0001;
+    public static final int EGL_GL_COLORSPACE_SRGB                         = 0x3089;
+    public static final int EGL_GL_COLORSPACE_LINEAR                       = 0x308A;
+    public static final int EGL_CONTEXT_MAJOR_VERSION                      = 0x3098;
+    public static final int EGL_CL_EVENT_HANDLE                            = 0x309C;
+    public static final int EGL_GL_COLORSPACE                              = 0x309D;
+    public static final int EGL_GL_TEXTURE_2D                              = 0x30B1;
+    public static final int EGL_GL_TEXTURE_3D                              = 0x30B2;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X             = 0x30B3;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X             = 0x30B4;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y             = 0x30B5;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y             = 0x30B6;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z             = 0x30B7;
+    public static final int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z             = 0x30B8;
+    public static final int EGL_GL_RENDERBUFFER                            = 0x30B9;
+    public static final int EGL_GL_TEXTURE_LEVEL                           = 0x30BC;
+    public static final int EGL_GL_TEXTURE_ZOFFSET                         = 0x30BD;
+    public static final int EGL_IMAGE_PRESERVED                            = 0x30D2;
+    public static final int EGL_SYNC_PRIOR_COMMANDS_COMPLETE               = 0x30F0;
+    public static final int EGL_SYNC_STATUS                                = 0x30F1;
+    public static final int EGL_SIGNALED                                   = 0x30F2;
+    public static final int EGL_UNSIGNALED                                 = 0x30F3;
+    public static final int EGL_TIMEOUT_EXPIRED                            = 0x30F5;
+    public static final int EGL_CONDITION_SATISFIED                        = 0x30F6;
+    public static final int EGL_SYNC_TYPE                                  = 0x30F7;
+    public static final int EGL_SYNC_CONDITION                             = 0x30F8;
+    public static final int EGL_SYNC_FENCE                                 = 0x30F9;
+    public static final int EGL_CONTEXT_MINOR_VERSION                      = 0x30FB;
+    public static final int EGL_CONTEXT_OPENGL_PROFILE_MASK                = 0x30FD;
+    public static final int EGL_SYNC_CL_EVENT                              = 0x30FE;
+    public static final int EGL_SYNC_CL_EVENT_COMPLETE                     = 0x30FF;
+    public static final int EGL_CONTEXT_OPENGL_DEBUG                       = 0x31B0;
+    public static final int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE          = 0x31B1;
+    public static final int EGL_CONTEXT_OPENGL_ROBUST_ACCESS               = 0x31B2;
+    public static final int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 0x31BD;
+    public static final int EGL_NO_RESET_NOTIFICATION                      = 0x31BE;
+    public static final int EGL_LOSE_CONTEXT_ON_RESET                      = 0x31BF;
+    public static final int EGL_PLATFORM_ANDROID_KHR                       = 0x3141;
+    public static final long EGL_FOREVER                                   = 0xFFFFFFFFFFFFFFFFL;
+    public static final EGLImage EGL_NO_IMAGE                              = null;
+    public static final EGLSync EGL_NO_SYNC                                = null;
+    public static final EGLContext EGL_NO_CONTEXT                          = null;
+    public static final EGLDisplay EGL_NO_DISPLAY                          = null;
+    public static final EGLSurface EGL_NO_SURFACE                          = null;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+    // C function EGLSync eglCreateSync ( EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list )
+
+    public static native EGLSync eglCreateSync(
+        EGLDisplay dpy,
+        int type,
+        long[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglDestroySync ( EGLDisplay dpy, EGLSync sync )
+
+    public static native boolean eglDestroySync(
+        EGLDisplay dpy,
+        EGLSync sync
+    );
+
+    // C function EGLint eglClientWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout )
+
+    public static native int eglClientWaitSync(
+        EGLDisplay dpy,
+        EGLSync sync,
+        int flags,
+        long timeout
+    );
+
+    // C function EGLBoolean eglGetSyncAttrib ( EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value )
+
+    public static native boolean eglGetSyncAttrib(
+        EGLDisplay dpy,
+        EGLSync sync,
+        int attribute,
+        long[] value,
+        int offset
+    );
+
+    // C function EGLDisplay eglGetPlatformDisplay ( EGLenum platform, EGLAttrib native_display, const EGLAttrib *attrib_list )
+
+    public static native EGLDisplay eglGetPlatformDisplay(
+        int platform,
+        long native_display,
+        long[] attrib_list,
+        int offset
+    );
+
+    // C function EGLSurface eglCreatePlatformWindowSurface ( EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list )
+
+    public static native EGLSurface eglCreatePlatformWindowSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        java.nio.Buffer native_window,
+        long[] attrib_list,
+        int offset
+    );
+
+    // C function EGLSurface eglCreatePlatformPixmapSurface ( EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list )
+
+    public static native EGLSurface eglCreatePlatformPixmapSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        java.nio.Buffer native_pixmap,
+        long[] attrib_list,
+        int offset
+    );
+
+    // C function EGLBoolean eglWaitSync ( EGLDisplay dpy, EGLSync sync, EGLint flags )
+
+    public static native boolean eglWaitSync(
+        EGLDisplay dpy,
+        EGLSync sync,
+        int flags
+    );
+
+}
diff --git a/opengl/java/android/opengl/EGLImage.java b/opengl/java/android/opengl/EGLImage.java
new file mode 100644
index 0000000..731ce72
--- /dev/null
+++ b/opengl/java/android/opengl/EGLImage.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLImage objects.
+ *
+ */
+public class EGLImage extends EGLObjectHandle {
+    private EGLImage(long handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof EGLImage)) return false;
+
+        EGLImage that = (EGLImage) o;
+        return getNativeHandle() == that.getNativeHandle();
+    }
+}
diff --git a/opengl/java/android/opengl/EGLSync.java b/opengl/java/android/opengl/EGLSync.java
new file mode 100644
index 0000000..472f9e7
--- /dev/null
+++ b/opengl/java/android/opengl/EGLSync.java
@@ -0,0 +1,37 @@
+/*
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.opengl;
+
+/**
+ * Wrapper class for native EGLSync objects.
+ *
+ */
+public class EGLSync extends EGLObjectHandle {
+    private EGLSync(long handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof EGLSync)) return false;
+
+        EGLSync that = (EGLSync) o;
+        return getNativeHandle() == that.getNativeHandle();
+    }
+}
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index d60dbe7..5161344 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -2,16 +2,14 @@
 
     name: "SettingsLib",
 
-    libs: [
+    static_libs: [
         "androidx.annotation_annotation",
         "androidx.legacy_legacy-support-v4",
         "androidx.recyclerview_recyclerview",
         "androidx.preference_preference",
         "androidx.appcompat_appcompat",
         "androidx.lifecycle_lifecycle-runtime",
-    ],
 
-    static_libs: [
         "SettingsLibHelpUtils",
         "SettingsLibRestrictedLockUtils",
         "SettingsLibAppPreference",
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/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 980ba87..e92656ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -60,7 +60,6 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.plugins.PluginManager;
@@ -71,7 +70,6 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.policy.DeadZone;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
@@ -140,6 +138,7 @@
     private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
     private final ContextualButtonGroup mContextualButtonGroup;
     private Configuration mConfiguration;
+    private Configuration mTmpLastConfiguration;
 
     private NavigationBarInflaterView mNavigationInflaterView;
     private RecentsOnboarding mRecentsOnboarding;
@@ -286,6 +285,7 @@
         mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
 
         mConfiguration = new Configuration();
+        mTmpLastConfiguration = new Configuration();
         mConfiguration.updateFrom(context.getResources().getConfiguration());
 
         mScreenPinningNotify = new ScreenPinningNotify(mContext);
@@ -445,13 +445,13 @@
     }
 
     private void reloadNavIcons() {
-        updateIcons(Configuration.EMPTY, mConfiguration);
+        updateIcons(Configuration.EMPTY);
     }
 
-    private void updateIcons(Configuration oldConfig, Configuration newConfig) {
-        final boolean orientationChange = oldConfig.orientation != newConfig.orientation;
-        final boolean densityChange = oldConfig.densityDpi != newConfig.densityDpi;
-        final boolean dirChange = oldConfig.getLayoutDirection() != newConfig.getLayoutDirection();
+    private void updateIcons(Configuration oldConfig) {
+        final boolean orientationChange = oldConfig.orientation != mConfiguration.orientation;
+        final boolean densityChange = oldConfig.densityDpi != mConfiguration.densityDpi;
+        final boolean dirChange = oldConfig.getLayoutDirection() != mConfiguration.getLayoutDirection();
 
         if (orientationChange || densityChange) {
             mDockedIcon = getDrawable(R.drawable.ic_sysbar_docked);
@@ -485,7 +485,7 @@
     private void orientBackButton(KeyButtonDrawable drawable) {
         final boolean useAltBack =
                 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
-        final boolean isRtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+        final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
         float degrees = useAltBack
                 ? (isRtl ? 270 : -90)
                 : (isRtl ? 180 : 0);
@@ -946,26 +946,27 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        boolean uiCarModeChanged = updateCarMode(newConfig);
+        mTmpLastConfiguration.updateFrom(mConfiguration);
+        mConfiguration.updateFrom(newConfig);
+        boolean uiCarModeChanged = updateCarMode();
         updateTaskSwitchHelper();
-        updateIcons(mConfiguration, newConfig);
+        updateIcons(mTmpLastConfiguration);
         updateRecentsIcon();
-        mRecentsOnboarding.onConfigurationChanged(newConfig);
-        if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
-                || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
+        mRecentsOnboarding.onConfigurationChanged(mConfiguration);
+        if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
+                || mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
             // If car mode or density changes, we need to reset the icons.
             updateNavButtonIcons();
         }
-        mConfiguration.updateFrom(newConfig);
     }
 
     /**
      * If the configuration changed, update the carmode and return that it was updated.
      */
-    private boolean updateCarMode(Configuration newConfig) {
+    private boolean updateCarMode() {
         boolean uiCarModeChanged = false;
-        if (newConfig != null) {
-            int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
+        if (mConfiguration != null) {
+            int uiMode = mConfiguration.uiMode & Configuration.UI_MODE_TYPE_MASK;
             final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
 
             if (isCarMode != mInCarMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 3bdd601..cc9adb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5277,8 +5277,7 @@
             (Runnable saveImportance, StatusBarNotification sbn) -> {
                 // If the user has security enabled, show challenge if the setting is changed.
                 if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier())
-                        && (mState == StatusBarState.KEYGUARD ||
-                                mState == StatusBarState.SHADE_LOCKED)) {
+                        && mKeyguardManager.isKeyguardLocked()) {
                     onLockedNotificationImportanceChange(() -> {
                         saveImportance.run();
                         return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 24a28cb..70a3589 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -461,6 +461,8 @@
                     MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                     controller.handleBroadcast(intent);
                 }
+                mConfig = Config.readConfig(mContext);
+                mReceiverHandler.post(this::handleConfigurationChanged);
                 break;
             case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
                 // Avoid rebroadcast because SysUI is direct boot aware.
@@ -1042,18 +1044,23 @@
             config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
             config.alwaysShowCdmaRssi =
                     res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
-            config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
             config.hspaDataDistinguishable =
                     res.getBoolean(R.bool.config_hspa_data_distinguishable);
-            config.hideLtePlus = res.getBoolean(R.bool.config_hideLtePlus);
             config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength);
 
             CarrierConfigManager configMgr = (CarrierConfigManager)
                     context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-            PersistableBundle b = configMgr.getConfig();
+            // Handle specific carrier config values for the default data SIM
+            int defaultDataSubId = SubscriptionManager.from(context)
+                    .getDefaultDataSubscriptionId();
+            PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
             if (b != null) {
                 config.alwaysShowDataRatIcon = b.getBoolean(
                         CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
+                config.show4gForLte = b.getBoolean(
+                        CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
+                config.hideLtePlus = b.getBoolean(
+                        CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
             }
             return config;
         }
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 30d14e6..f85749a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -312,8 +312,8 @@
                                 Slog.d(TAG, "Setting urlBar as id=" + urlBarId + " and domain "
                                         + mUrlBar.getWebDomain());
                             }
-                            final ViewState viewState = new ViewState(Session.this, urlBarId,
-                                    Session.this, ViewState.STATE_URL_BAR);
+                            final ViewState viewState = new ViewState(urlBarId, Session.this,
+                                    ViewState.STATE_URL_BAR);
                             mViewStates.put(urlBarId, viewState);
                         }
                     }
@@ -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;
     }
 
@@ -2149,7 +2156,7 @@
                     || action == ACTION_VIEW_ENTERED) {
                 if (sVerbose) Slog.v(TAG, "Creating viewState for " + id);
                 boolean isIgnored = isIgnoredLocked(id);
-                viewState = new ViewState(this, id, this,
+                viewState = new ViewState(id, this,
                         isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
                 mViewStates.put(id, viewState);
 
@@ -2629,7 +2636,7 @@
         if (viewState != null)  {
             viewState.setState(state);
         } else {
-            viewState = new ViewState(this, id, this, state);
+            viewState = new ViewState(id, this, state);
             if (sVerbose) {
                 Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
             }
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index 49778f5..2cc6d20 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -77,7 +77,6 @@
     public final AutofillId id;
 
     private final Listener mListener;
-    private final Session mSession;
 
     private FillResponse mResponse;
     private AutofillValue mCurrentValue;
@@ -87,8 +86,7 @@
     private int mState;
     private String mDatasetId;
 
-    ViewState(Session session, AutofillId id, Listener listener, int state) {
-        mSession = session;
+    ViewState(AutofillId id, Listener listener, int state) {
         this.id = id;
         mListener = listener;
         mState = state;
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 0b836f0..9cc550d 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -528,7 +528,7 @@
             Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
                     public void run() {
                         mActivity.addErrorToDropBox(
-                                "watchdog", null, "system_server", null, null,
+                                "watchdog", null, "system_server", null, null, null,
                                 subject, null, stack, null);
                     }
                 };
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f4ec1f9..7235312 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3641,7 +3641,7 @@
         }
 
         if (anrMessage != null) {
-            mAm.mAppErrors.appNotResponding(proc, null, null, false, anrMessage);
+            proc.appNotResponding(null, null, null, null, false, anrMessage);
         }
     }
 
@@ -3666,7 +3666,7 @@
         }
 
         if (app != null) {
-            mAm.mAppErrors.appNotResponding(app, null, null, false,
+            app.appNotResponding(null, null, null, null, false,
                     "Context.startForegroundService() did not then call Service.startForeground(): "
                         + r);
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2486787..c27ec6f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18,9 +18,9 @@
 
 import static android.Manifest.permission.CHANGE_CONFIGURATION;
 import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
+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;
@@ -28,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;
@@ -101,9 +99,6 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
@@ -116,15 +111,12 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USAGE_STATS;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_WHITELISTS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BACKUP;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_NETWORK;
@@ -135,11 +127,16 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PROVIDER;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PSS;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
 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.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
 import static com.android.server.am.ActivityTaskManagerService.DUMP_ACTIVITIES_CMD;
 import static com.android.server.am.ActivityTaskManagerService.DUMP_ACTIVITIES_SHORT_CMD;
 import static com.android.server.am.ActivityTaskManagerService.DUMP_CONTAINERS_CMD;
@@ -148,6 +145,10 @@
 import static com.android.server.am.ActivityTaskManagerService.DUMP_RECENTS_CMD;
 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.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
 import static com.android.server.am.MemoryStatUtil.hasMemcg;
 import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
@@ -164,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;
@@ -367,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;
@@ -458,6 +455,12 @@
     // before we decide it must be hung.
     static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000;
 
+    /**
+     * How long we wait for an provider to be published. Should be longer than
+     * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT}.
+     */
+    static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 1000;
+
     // How long we wait for a launched process to attach to the activity manager
     // before we decide it's never going to come up for real, when the process was
     // started with a wrapper for instrumentation (such as Valgrind) because it
@@ -501,6 +504,9 @@
      */
     private static final long NETWORK_ACCESS_TIMEOUT_DEFAULT_MS = 200; // 0.2 sec
 
+    // The minimum memory growth threshold (in KB) for low RAM devices.
+    private static final int MINIMUM_MEMORY_GROWTH_THRESHOLD = 10 * 1000; // 10 MB
+
     /**
      * State indicating that there is no need for any blocking for network.
      */
@@ -7374,6 +7380,7 @@
         ContentProviderRecord cpr;
         ContentProviderConnection conn = null;
         ProviderInfo cpi = null;
+        boolean providerRunning = false;
 
         synchronized(this) {
             long startTime = SystemClock.uptimeMillis();
@@ -7413,8 +7420,6 @@
                 }
             }
 
-            boolean providerRunning = false;
-
             if (cpr != null && cpr.proc != null) {
                 providerRunning = !cpr.proc.killed;
 
@@ -7739,6 +7744,7 @@
         }
 
         // Wait for the provider to be published...
+        final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT;
         synchronized (cpr) {
             while (cpr.provider == null) {
                 if (cpr.launchingApp == null) {
@@ -7753,13 +7759,22 @@
                     return null;
                 }
                 try {
+                    final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis());
                     if (DEBUG_MU) Slog.v(TAG_MU,
                             "Waiting to start provider " + cpr
-                            + " launchingApp=" + cpr.launchingApp);
+                            + " launchingApp=" + cpr.launchingApp + " for " + wait + " ms");
                     if (conn != null) {
                         conn.waiting = true;
                     }
-                    cpr.wait();
+                    cpr.wait(wait);
+                    if (cpr.provider == null) {
+                        Slog.wtf(TAG, "Timeout waiting for provider "
+                                + cpi.applicationInfo.packageName + "/"
+                                + cpi.applicationInfo.uid + " for provider "
+                                + name
+                                + " providerRunning=" + providerRunning);
+                        return null;
+                    }
                 } catch (InterruptedException ex) {
                 } finally {
                     if (conn != null) {
@@ -8119,8 +8134,8 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                mAppErrors.appNotResponding(host, null, null, false,
-                        "ContentProvider not responding");
+                host.appNotResponding(
+                        null, null, null, null, false, "ContentProvider not responding");
             }
         });
     }
@@ -9460,6 +9475,11 @@
             // If at least 1/3 of our time since the last idle period has been spent
             // with RAM low, then we want to kill processes.
             boolean doKilling = lowRamSinceLastIdle > (timeSinceLastIdle/3);
+            // If the processes' memory has increased by more than 1% of the total memory,
+            // or 10 MB, whichever is greater, then the processes' are eligible to be killed.
+            final long totalMemoryInKb = getTotalMemory() / 1000;
+            final long memoryGrowthThreshold =
+                    Math.max(totalMemoryInKb / 100, MINIMUM_MEMORY_GROWTH_THRESHOLD);
 
             for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
                 ProcessRecord proc = mLruProcesses.get(i);
@@ -9467,7 +9487,8 @@
                     if (proc.setProcState >= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                             && proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) {
                         if (doKilling && proc.initialIdlePss != 0
-                                && proc.lastPss > ((proc.initialIdlePss*3)/2)) {
+                                && proc.lastPss > ((proc.initialIdlePss * 3) / 2)
+                                && proc.lastPss > (proc.initialIdlePss + memoryGrowthThreshold)) {
                             sb = new StringBuilder(128);
                             sb.append("Kill");
                             sb.append(proc.processName);
@@ -9781,16 +9802,17 @@
                         : 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 {
             crashInfo.crashTag = crashInfo.crashTag + " " + relaunchReasonString;
         }
 
-        addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo);
+        addErrorToDropBox(
+                eventType, r, processName, null, null, null, null, null, null, crashInfo);
 
         mAppErrors.crashApplication(r, crashInfo);
     }
@@ -9962,7 +9984,7 @@
         StatsLog.write(StatsLog.WTF_OCCURRED, callingUid, tag, processName,
                 callingPid);
 
-        addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
+        addErrorToDropBox("wtf", r, processName, null, null, null, tag, null, null, crashInfo);
 
         return r;
     }
@@ -10061,17 +10083,18 @@
      * Write a description of an error (crash, WTF, ANR) to the drop box.
      * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
      * @param process which caused the error, null means the system server
-     * @param activity which triggered the error, null if unknown
-     * @param parent activity related to the error, null if unknown
+     * @param activityShortComponentName which triggered the error, null if unknown
+     * @param parentShortComponentName activity related to the error, null if unknown
+     * @param parentProcess parent process
      * @param subject line related to the error, null if absent
      * @param report in long form describing the error, null if absent
      * @param dataFile text file to include in the report, null if none
      * @param crashInfo giving an application stack trace, null if absent
      */
     public void addErrorToDropBox(String eventType,
-            ProcessRecord process, String processName, ActivityRecord activity,
-            ActivityRecord parent, String subject,
-            final String report, final File dataFile,
+            ProcessRecord process, String processName, String activityShortComponentName,
+            String parentShortComponentName, ProcessRecord parentProcess,
+            String subject, final String report, final File dataFile,
             final ApplicationErrorReport.CrashInfo crashInfo) {
         // NOTE -- this must never acquire the ActivityManagerService lock,
         // otherwise the watchdog may be prevented from resetting the system.
@@ -10101,14 +10124,16 @@
                     .append(process.isInterestingToUserLocked() ? "Yes" : "No")
                     .append("\n");
         }
-        if (activity != null) {
-            sb.append("Activity: ").append(activity.shortComponentName).append("\n");
+        if (activityShortComponentName != null) {
+            sb.append("Activity: ").append(activityShortComponentName).append("\n");
         }
-        if (parent != null && parent.app != null && parent.app.getPid() != process.pid) {
-            sb.append("Parent-Process: ").append(parent.app.mName).append("\n");
-        }
-        if (parent != null && parent != activity) {
-            sb.append("Parent-Activity: ").append(parent.shortComponentName).append("\n");
+        if (parentShortComponentName != null) {
+            if (parentProcess != null && parentProcess.pid != process.pid) {
+                sb.append("Parent-Process: ").append(parentProcess.processName).append("\n");
+            }
+            if (!parentShortComponentName.equals(activityShortComponentName)) {
+                sb.append("Parent-Activity: ").append(parentShortComponentName).append("\n");
+            }
         }
         if (subject != null) {
             sb.append("Subject: ").append(subject).append("\n");
@@ -13983,7 +14008,7 @@
         dropBuilder.append(catSw.toString());
         StatsLog.write(StatsLog.LOW_MEM_REPORTED);
         addErrorToDropBox("lowmem", null, "system_server", null,
-                null, tag.toString(), dropBuilder.toString(), null, null);
+                null, null, tag.toString(), dropBuilder.toString(), null, null);
         //Slog.i(TAG, "Sent to dropbox:");
         //Slog.i(TAG, dropBuilder.toString());
         synchronized (ActivityManagerService.this) {
@@ -20295,6 +20320,83 @@
                         : UsageEvents.Event.KEYGUARD_HIDDEN);
             }
         }
+
+        @Override
+        public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason) {
+            synchronized (ActivityManagerService.this) {
+                return ActivityManagerService.this.inputDispatchingTimedOut(
+                        pid, aboveSystem, reason);
+            }
+        }
+
+        @Override
+        public boolean inputDispatchingTimedOut(Object proc, String activityShortComponentName,
+                ApplicationInfo aInfo, String parentShortComponentName, Object parentProc,
+                boolean aboveSystem, String reason) {
+            return ActivityManagerService.this.inputDispatchingTimedOut((ProcessRecord) proc,
+                    activityShortComponentName, aInfo, parentShortComponentName,
+                    (WindowProcessController) parentProc, aboveSystem, reason);
+
+        }
+    }
+
+    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires permission " + FILTER_EVENTS);
+        }
+        ProcessRecord proc;
+        long timeout;
+        synchronized (this) {
+            synchronized (mPidsSelfLocked) {
+                proc = mPidsSelfLocked.get(pid);
+            }
+            timeout = proc != null ? proc.getInputDispatchingTimeout() : KEY_DISPATCHING_TIMEOUT_MS;
+        }
+
+        if (inputDispatchingTimedOut(proc, null, null, null, null, aboveSystem, reason)) {
+            return -1;
+        }
+
+        return timeout;
+    }
+
+    /**
+     * Handle input dispatching timeouts.
+     * @return whether input dispatching should be aborted or not.
+     */
+    boolean inputDispatchingTimedOut(ProcessRecord proc, String activityShortComponentName,
+            ApplicationInfo aInfo, String parentShortComponentName,
+            WindowProcessController parentProcess, boolean aboveSystem, String reason) {
+        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires permission " + FILTER_EVENTS);
+        }
+
+        final String annotation;
+        if (reason == null) {
+            annotation = "Input dispatching timed out";
+        } else {
+            annotation = "Input dispatching timed out (" + reason + ")";
+        }
+
+        if (proc != null) {
+            synchronized (this) {
+                if (proc.isDebugging()) {
+                    return false;
+                }
+
+                if (proc.getActiveInstrumentation() != null) {
+                    Bundle info = new Bundle();
+                    info.putString("shortMsg", "keyDispatchingTimedOut");
+                    info.putString("longMsg", annotation);
+                    finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
+                    return true;
+                }
+            }
+            proc.appNotResponding(activityShortComponentName, aInfo,
+                    parentShortComponentName, parentProcess, aboveSystem, annotation);
+        }
+
+        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d837118..865c774 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.
@@ -2114,12 +2112,16 @@
             windowFromSameProcessAsActivity =
                     !hasProcess() || app.getPid() == windowPid || windowPid == -1;
         }
+
         if (windowFromSameProcessAsActivity) {
-            return service.inputDispatchingTimedOut(anrApp, anrActivity, this, false, reason);
+            return service.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
+                    anrActivity.shortComponentName, anrActivity.appInfo, shortComponentName,
+                    app, false, reason);
         } else {
             // In this case another process added windows using this activity token. So, we call the
             // generic service input dispatch timed out method so that the right process is blamed.
-            return service.inputDispatchingTimedOut(windowPid, false /* aboveSystem */, reason) < 0;
+            return service.mAmInternal.inputDispatchingTimedOut(
+                    windowPid, false /* aboveSystem */, reason) < 0;
         }
     }
 
@@ -2211,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;
     }
@@ -2281,6 +2284,11 @@
             // We don't show starting window for overlay activities.
             return;
         }
+        if (pendingOptions != null
+                && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+            // Don't show starting window when using shared element transition.
+            return;
+        }
 
         final CompatibilityInfo compatInfo =
                 service.compatibilityInfoForPackageLocked(info.applicationInfo);
@@ -3006,17 +3014,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 b7bbfe8..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,... ).
@@ -295,9 +294,9 @@
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
 
     // How long we wait until we timeout on key dispatching.
-    private static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
+    public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
     // How long we wait until we timeout on key dispatching during instrumentation.
-    private static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+    static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
 
     /** Used to indicate that an app transition should be animated. */
     static final boolean ANIMATE = true;
@@ -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();
     }
@@ -4932,70 +4950,7 @@
     }
 
     private static long getInputDispatchingTimeoutLocked(WindowProcessController r) {
-        if (r != null && (r.isInstrumenting() || r.isUsingWrapper())) {
-            return INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
-        }
-        return KEY_DISPATCHING_TIMEOUT_MS;
-    }
-
-    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
-        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires permission " + FILTER_EVENTS);
-        }
-        WindowProcessController proc;
-        long timeout;
-        synchronized (mGlobalLock) {
-            proc = mPidMap.get(pid);
-            timeout = getInputDispatchingTimeoutLocked(proc);
-        }
-
-        if (inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
-            return -1;
-        }
-
-        return timeout;
-    }
-
-    /**
-     * Handle input dispatching timeouts.
-     * Returns whether input dispatching should be aborted or not.
-     */
-    boolean inputDispatchingTimedOut(final WindowProcessController proc,
-            final ActivityRecord activity, final ActivityRecord parent,
-            final boolean aboveSystem, String reason) {
-        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires permission " + FILTER_EVENTS);
-        }
-
-        final String annotation;
-        if (reason == null) {
-            annotation = "Input dispatching timed out";
-        } else {
-            annotation = "Input dispatching timed out (" + reason + ")";
-        }
-
-        if (proc != null) {
-            synchronized (mGlobalLock) {
-                if (proc.isDebugging()) {
-                    return false;
-                }
-
-                if (proc.isInstrumenting()) {
-                    Bundle info = new Bundle();
-                    info.putString("shortMsg", "keyDispatchingTimedOut");
-                    info.putString("longMsg", annotation);
-                    mAm.finishInstrumentationLocked(
-                            (ProcessRecord) proc.mOwner, Activity.RESULT_CANCELED, info);
-                    return true;
-                }
-            }
-            mH.post(() -> {
-                mAm.mAppErrors.appNotResponding(
-                        (ProcessRecord) proc.mOwner, activity, parent, aboveSystem, annotation);
-            });
-        }
-
-        return true;
+        return r != null ? r.getInputDispatchingTimeout() : KEY_DISPATCHING_TIMEOUT_MS;
     }
 
     /**
@@ -6031,14 +5986,6 @@
         }
 
         @Override
-        public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason) {
-            synchronized (mGlobalLock) {
-                return ActivityTaskManagerService.this.inputDispatchingTimedOut(
-                        pid, aboveSystem, reason);
-            }
-        }
-
-        @Override
         public void onProcessMapped(int pid, WindowProcessController proc) {
             synchronized (mGlobalLock) {
                 mPidMap.put(pid, proc);
@@ -6619,19 +6566,18 @@
 
                 if (mHomeProcess != null && (dumpPackage == null
                         || mHomeProcess.mPkgList.contains(dumpPackage))) {
-                    ((ProcessRecord) mHomeProcess.mOwner).writeToProto(proto, HOME_PROC);
+                    mHomeProcess.writeToProto(proto, HOME_PROC);
                 }
 
                 if (mPreviousProcess != null && (dumpPackage == null
                         || mPreviousProcess.mPkgList.contains(dumpPackage))) {
-                    ((ProcessRecord) mPreviousProcess.mOwner).writeToProto(proto, PREVIOUS_PROC);
+                    mPreviousProcess.writeToProto(proto, PREVIOUS_PROC);
                     proto.write(PREVIOUS_PROC_VISIBLE_TIME_MS, mPreviousProcessVisibleTime);
                 }
 
                 if (mHeavyWeightProcess != null && (dumpPackage == null
                         || mHeavyWeightProcess.mPkgList.contains(dumpPackage))) {
-                    ((ProcessRecord) mHeavyWeightProcess.mOwner).writeToProto(
-                            proto, HEAVY_WEIGHT_PROC);
+                    mHeavyWeightProcess.writeToProto(proto, HEAVY_WEIGHT_PROC);
                 }
 
                 for (Map.Entry<String, Integer> entry
@@ -6714,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 be1f9ea..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);
                     }
                 }
             }
@@ -582,27 +568,12 @@
         app.setCrashing(true);
         app.crashingReport = generateProcessError(app,
                 ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace);
-        startAppProblemLocked(app);
+        app.startAppProblemLocked();
         app.getWindowProcessController().stopFreezingActivities();
         return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace,
                 data);
     }
 
-    void startAppProblemLocked(ProcessRecord app) {
-        // If this app is not running under the current user, then we
-        // can't give it a report button because that would require
-        // launching the report UI under a different user.
-        app.errorReportReceiver = null;
-
-        for (int userId : mService.mUserController.getCurrentProfileIds()) {
-            if (app.userId == userId) {
-                app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
-                        mContext, app.info.packageName, app.info.flags);
-            }
-        }
-        mService.skipCurrentReceiverLocked(app);
-    }
-
     /**
      * Generate a process error record, suitable for attachment to a ProcessRecord.
      *
@@ -616,7 +587,7 @@
      *
      * @return Returns a fully-formed ProcessErrorStateInfo record.
      */
-    private ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
+    ActivityManager.ProcessErrorStateInfo generateProcessError(ProcessRecord app,
             int condition, String activity, String shortMsg, String longMsg, String stackTrace) {
         ActivityManager.ProcessErrorStateInfo report = new ActivityManager.ProcessErrorStateInfo();
 
@@ -751,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) {
@@ -855,259 +825,13 @@
         }
     }
 
-    void stopReportingCrashesLocked(ProcessRecord proc) {
+    private void stopReportingCrashesLocked(ProcessRecord proc) {
         if (mAppsNotReportingCrashes == null) {
             mAppsNotReportingCrashes = new ArraySet<>();
         }
         mAppsNotReportingCrashes.add(proc.info.packageName);
     }
 
-    static boolean isInterestingForBackgroundTraces(ProcessRecord app) {
-        // The system_server is always considered interesting.
-        if (app.pid == MY_PID) {
-            return true;
-        }
-
-        // A package is considered interesting if any of the following is true :
-        //
-        // - It's displaying an activity.
-        // - It's the SystemUI.
-        // - It has an overlay or a top UI visible.
-        //
-        // NOTE: The check whether a given ProcessRecord belongs to the systemui
-        // process is a bit of a kludge, but the same pattern seems repeated at
-        // several places in the system server.
-        return app.isInterestingToUserLocked() ||
-            (app.info != null && "com.android.systemui".equals(app.info.packageName)) ||
-            (app.hasTopUi() || app.hasOverlayUi());
-    }
-
-    final void appNotResponding(ProcessRecord app, ActivityRecord activity,
-            ActivityRecord parent, boolean aboveSystem, final String annotation) {
-        ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
-        SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
-
-        if (mService.mActivityTaskManager.mController != null) {
-            try {
-                // 0 == continue, -1 = kill process immediately
-                int res = mService.mActivityTaskManager.mController.appEarlyNotResponding(
-                        app.processName, app.pid, annotation);
-                if (res < 0 && app.pid != MY_PID) {
-                    app.kill("anr", true);
-                }
-            } catch (RemoteException e) {
-                mService.mActivityTaskManager.mController = null;
-                Watchdog.getInstance().setActivityController(null);
-            }
-        }
-
-        long anrTime = SystemClock.uptimeMillis();
-        if (ActivityManagerService.MONITOR_CPU_USAGE) {
-            mService.updateCpuStatsNow();
-        }
-
-        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
-        boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-
-        boolean isSilentANR;
-
-        synchronized (mService) {
-            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
-            if (mService.mActivityTaskManager.mShuttingDown) {
-                Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
-                return;
-            } else if (app.isNotResponding()) {
-                Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
-                return;
-            } else if (app.isCrashing()) {
-                Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
-                return;
-            } else if (app.killedByAm) {
-                Slog.i(TAG, "App already killed by AM skipping ANR: " + app + " " + annotation);
-                return;
-            } else if (app.killed) {
-                Slog.i(TAG, "Skipping died app ANR: " + app + " " + annotation);
-                return;
-            }
-
-            // In case we come through here for the same app before completing
-            // this one, mark as anring now so we will bail out.
-            app.setNotResponding(true);
-
-            // Log the ANR to the event log.
-            EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
-                    app.processName, app.info.flags, annotation);
-
-            // Dump thread traces as quickly as we can, starting with "interesting" processes.
-            firstPids.add(app.pid);
-
-            // Don't dump other PIDs if it's a background ANR
-            isSilentANR = !showBackground && !isInterestingForBackgroundTraces(app);
-            if (!isSilentANR) {
-                int parentPid = app.pid;
-                if (parent != null && parent.app != null && parent.app.getPid() > 0) {
-                    parentPid = parent.app.getPid();
-                }
-                if (parentPid != app.pid) firstPids.add(parentPid);
-
-                if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
-
-                for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
-                    ProcessRecord r = mService.mLruProcesses.get(i);
-                    if (r != null && r.thread != null) {
-                        int pid = r.pid;
-                        if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
-                            if (r.isPersistent()) {
-                                firstPids.add(pid);
-                                if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
-                            } else if (r.treatLikeActivity) {
-                                firstPids.add(pid);
-                                if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
-                            } else {
-                                lastPids.put(pid, Boolean.TRUE);
-                                if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // Log the ANR to the main log.
-        StringBuilder info = new StringBuilder();
-        info.setLength(0);
-        info.append("ANR in ").append(app.processName);
-        if (activity != null && activity.shortComponentName != null) {
-            info.append(" (").append(activity.shortComponentName).append(")");
-        }
-        info.append("\n");
-        info.append("PID: ").append(app.pid).append("\n");
-        if (annotation != null) {
-            info.append("Reason: ").append(annotation).append("\n");
-        }
-        if (parent != null && parent != activity) {
-            info.append("Parent: ").append(parent.shortComponentName).append("\n");
-        }
-
-        ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
-
-        // don't dump native PIDs for background ANRs unless it is the process of interest
-        String[] nativeProcs = null;
-        if (isSilentANR) {
-            for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
-                if (NATIVE_STACKS_OF_INTEREST[i].equals(app.processName)) {
-                    nativeProcs = new String[] { app.processName };
-                    break;
-                }
-            }
-        } else {
-            nativeProcs = NATIVE_STACKS_OF_INTEREST;
-        }
-
-        int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
-        ArrayList<Integer> nativePids = null;
-
-        if (pids != null) {
-            nativePids = new ArrayList<Integer>(pids.length);
-            for (int i : pids) {
-                nativePids.add(i);
-            }
-        }
-
-        // For background ANRs, don't pass the ProcessCpuTracker to
-        // avoid spending 1/2 second collecting stats to rank lastPids.
-        File tracesFile = ActivityManagerService.dumpStackTraces(
-                firstPids,
-                (isSilentANR) ? null : processCpuTracker,
-                (isSilentANR) ? null : lastPids,
-                nativePids);
-
-        String cpuInfo = null;
-        if (ActivityManagerService.MONITOR_CPU_USAGE) {
-            mService.updateCpuStatsNow();
-            synchronized (mService.mProcessCpuTracker) {
-                cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
-            }
-            info.append(processCpuTracker.printCurrentLoad());
-            info.append(cpuInfo);
-        }
-
-        info.append(processCpuTracker.printCurrentState(anrTime));
-
-        Slog.e(TAG, info.toString());
-        if (tracesFile == null) {
-            // There is no trace file, so dump (only) the alleged culprit's threads to the log
-            Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
-        }
-
-        StatsLog.write(StatsLog.ANR_OCCURRED, app.uid, app.processName,
-                activity == null ? "unknown": activity.shortComponentName, annotation,
-                (app.info != null) ? (app.info.isInstantApp()
-                        ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
-                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
-                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
-                app != null ? (app.isInterestingToUserLocked()
-                        ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
-                        : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND)
-                        : StatsLog.ANROCCURRED__FOREGROUND_STATE__UNKNOWN);
-        mService.addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
-                cpuInfo, tracesFile, null);
-
-        if (mService.mActivityTaskManager.mController != null) {
-            try {
-                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
-                int res = mService.mActivityTaskManager.mController.appNotResponding(
-                        app.processName, app.pid, info.toString());
-                if (res != 0) {
-                    if (res < 0 && app.pid != MY_PID) {
-                        app.kill("anr", true);
-                    } else {
-                        synchronized (mService) {
-                            mService.mServices.scheduleServiceTimeoutLocked(app);
-                        }
-                    }
-                    return;
-                }
-            } catch (RemoteException e) {
-                mService.mActivityTaskManager.mController = null;
-                Watchdog.getInstance().setActivityController(null);
-            }
-        }
-
-        synchronized (mService) {
-            mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
-
-            if (isSilentANR) {
-                app.kill("bg anr", true);
-                return;
-            }
-
-            // Set the app's notResponding state, and look up the errorReportReceiver
-            makeAppNotRespondingLocked(app,
-                    activity != null ? activity.shortComponentName : null,
-                    annotation != null ? "ANR " + annotation : "ANR",
-                    info.toString());
-
-            // Bring up the infamous App Not Responding dialog
-            Message msg = Message.obtain();
-            msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
-            msg.obj = new AppNotRespondingDialog.Data(app, activity, aboveSystem);
-
-            mService.mUiHandler.sendMessage(msg);
-        }
-    }
-
-    private void makeAppNotRespondingLocked(ProcessRecord app,
-            String activity, String shortMsg, String longMsg) {
-        app.setNotResponding(true);
-        app.notRespondingReport = generateProcessError(app,
-                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
-                activity, shortMsg, longMsg, null);
-        startAppProblemLocked(app);
-        app.getWindowProcessController().stopFreezingActivities();
-    }
-
     void handleShowAnrUi(Message msg) {
         Dialog dialogToShow = null;
         synchronized (mService) {
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 7c983ff..cb76e2f 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.content.pm.ApplicationInfo;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 
@@ -58,8 +59,8 @@
         setCancelable(false);
 
         int resid;
-        CharSequence name1 = data.activity != null
-                ? data.activity.info.loadLabel(context.getPackageManager())
+        CharSequence name1 = data.aInfo != null
+                ? data.aInfo.loadLabel(context.getPackageManager())
                 : null;
         CharSequence name2 = null;
         if ((mProc.pkgList.size() == 1) &&
@@ -181,12 +182,12 @@
 
     static class Data {
         final ProcessRecord proc;
-        final ActivityRecord activity;
+        final ApplicationInfo aInfo;
         final boolean aboveSystem;
 
-        Data(ProcessRecord proc, ActivityRecord activity, boolean aboveSystem) {
+        Data(ProcessRecord proc, ApplicationInfo aInfo, boolean aboveSystem) {
             this.proc = proc;
-            this.activity = activity;
+            this.aInfo = aInfo;
             this.aboveSystem = aboveSystem;
         }
     }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index e2035f6..a13cf4d 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -191,7 +191,7 @@
 
         @Override
         public void run() {
-            mService.mAppErrors.appNotResponding(mApp, null, null, false, mAnnotation);
+            mApp.appNotResponding(null, null, null, null, false, mAnnotation);
         }
     }
 
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/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index b9c6fa6..2dcddff 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -288,12 +288,19 @@
                 resolvedType = key.requestResolvedType;
             }
 
+            // Apply any launch flags from the ActivityOptions. This is to ensure that the caller
+            // can specify a consistent launch mode even if the PendingIntent is immutable
+            final ActivityOptions opts = ActivityOptions.fromBundle(options);
+            if (opts != null) {
+                finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
+            }
+
             // Extract options before clearing calling identity
             mergedOptions = key.options;
             if (mergedOptions == null) {
-                mergedOptions = SafeActivityOptions.fromBundle(options);
+                mergedOptions = new SafeActivityOptions(opts);
             } else {
-                mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
+                mergedOptions.setCallerOptions(opts);
             }
 
             if (whitelistDuration != null) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 145791c..0eb535b 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -18,10 +18,14 @@
 
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 
+import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
 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 android.app.ActivityManager;
+import android.app.ApplicationErrorReport;
 import android.app.Dialog;
 import android.app.IApplicationThread;
 import android.content.ComponentName;
@@ -32,16 +36,19 @@
 import android.os.Binder;
 import android.os.Debug;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DebugUtils;
 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;
@@ -49,7 +56,10 @@
 import com.android.internal.app.procstats.ProcessState;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.os.BatteryStatsImpl;
+import com.android.internal.os.ProcessCpuTracker;
+import com.android.server.Watchdog;
 
+import java.io.File;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -735,6 +745,7 @@
         }
     }
 
+    @Override
     public void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
         proto.write(ProcessRecordProto.PID, pid);
@@ -1168,4 +1179,267 @@
     public long getCpuTime() {
         return mService.mProcessCpuTracker.getCpuTimeForPid(pid);
     }
+
+    public long getInputDispatchingTimeout() {
+        return mWindowProcessController.getInputDispatchingTimeout();
+    }
+
+    void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
+            String parentShortComponentName, WindowProcessController parentProcess,
+            boolean aboveSystem, String annotation) {
+        ArrayList<Integer> firstPids = new ArrayList<>(5);
+        SparseArray<Boolean> lastPids = new SparseArray<>(20);
+
+        if (mService.mActivityTaskManager.mController != null) {
+            try {
+                // 0 == continue, -1 = kill process immediately
+                int res = mService.mActivityTaskManager.mController.appEarlyNotResponding(
+                        processName, pid, annotation);
+                if (res < 0 && pid != MY_PID) {
+                    kill("anr", true);
+                }
+            } catch (RemoteException e) {
+                mService.mActivityTaskManager.mController = null;
+                Watchdog.getInstance().setActivityController(null);
+            }
+        }
+
+        long anrTime = SystemClock.uptimeMillis();
+        if (ActivityManagerService.MONITOR_CPU_USAGE) {
+            mService.updateCpuStatsNow();
+        }
+
+        // Unless configured otherwise, swallow ANRs in background processes & kill the process.
+        boolean showBackground = Settings.Secure.getInt(mService.mContext.getContentResolver(),
+                Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+
+        boolean isSilentANR;
+
+        synchronized (mService) {
+            // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
+            if (mService.mActivityTaskManager.mShuttingDown) {
+                Slog.i(TAG, "During shutdown skipping ANR: " + this + " " + annotation);
+                return;
+            } else if (isNotResponding()) {
+                Slog.i(TAG, "Skipping duplicate ANR: " + this + " " + annotation);
+                return;
+            } else if (isCrashing()) {
+                Slog.i(TAG, "Crashing app skipping ANR: " + this + " " + annotation);
+                return;
+            } else if (killedByAm) {
+                Slog.i(TAG, "App already killed by AM skipping ANR: " + this + " " + annotation);
+                return;
+            } else if (killed) {
+                Slog.i(TAG, "Skipping died app ANR: " + this + " " + annotation);
+                return;
+            }
+
+            // In case we come through here for the same app before completing
+            // this one, mark as anring now so we will bail out.
+            setNotResponding(true);
+
+            // Log the ANR to the event log.
+            EventLog.writeEvent(EventLogTags.AM_ANR, userId, pid, processName, info.flags,
+                    annotation);
+
+            // Dump thread traces as quickly as we can, starting with "interesting" processes.
+            firstPids.add(pid);
+
+            // Don't dump other PIDs if it's a background ANR
+            isSilentANR = !showBackground && !isInterestingForBackgroundTraces();
+            if (!isSilentANR) {
+                int parentPid = pid;
+                if (parentProcess != null && parentProcess.getPid() > 0) {
+                    parentPid = parentProcess.getPid();
+                }
+                if (parentPid != pid) firstPids.add(parentPid);
+
+                if (MY_PID != pid && MY_PID != parentPid) firstPids.add(MY_PID);
+
+                for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
+                    ProcessRecord r = mService.mLruProcesses.get(i);
+                    if (r != null && r.thread != null) {
+                        int myPid = r.pid;
+                        if (myPid > 0 && myPid != pid && myPid != parentPid && myPid != MY_PID) {
+                            if (r.isPersistent()) {
+                                firstPids.add(myPid);
+                                if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
+                            } else if (r.treatLikeActivity) {
+                                firstPids.add(myPid);
+                                if (DEBUG_ANR) Slog.i(TAG, "Adding likely IME: " + r);
+                            } else {
+                                lastPids.put(myPid, Boolean.TRUE);
+                                if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Log the ANR to the main log.
+        StringBuilder info = new StringBuilder();
+        info.setLength(0);
+        info.append("ANR in ").append(processName);
+        if (activityShortComponentName != null) {
+            info.append(" (").append(activityShortComponentName).append(")");
+        }
+        info.append("\n");
+        info.append("PID: ").append(pid).append("\n");
+        if (annotation != null) {
+            info.append("Reason: ").append(annotation).append("\n");
+        }
+        if (parentShortComponentName != null
+                && parentShortComponentName.equals(activityShortComponentName)) {
+            info.append("Parent: ").append(parentShortComponentName).append("\n");
+        }
+
+        ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
+
+        // don't dump native PIDs for background ANRs unless it is the process of interest
+        String[] nativeProcs = null;
+        if (isSilentANR) {
+            for (int i = 0; i < NATIVE_STACKS_OF_INTEREST.length; i++) {
+                if (NATIVE_STACKS_OF_INTEREST[i].equals(processName)) {
+                    nativeProcs = new String[] { processName };
+                    break;
+                }
+            }
+        } else {
+            nativeProcs = NATIVE_STACKS_OF_INTEREST;
+        }
+
+        int[] pids = nativeProcs == null ? null : Process.getPidsForCommands(nativeProcs);
+        ArrayList<Integer> nativePids = null;
+
+        if (pids != null) {
+            nativePids = new ArrayList<>(pids.length);
+            for (int i : pids) {
+                nativePids.add(i);
+            }
+        }
+
+        // For background ANRs, don't pass the ProcessCpuTracker to
+        // avoid spending 1/2 second collecting stats to rank lastPids.
+        File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
+                (isSilentANR) ? null : processCpuTracker, (isSilentANR) ? null : lastPids,
+                nativePids);
+
+        String cpuInfo = null;
+        if (ActivityManagerService.MONITOR_CPU_USAGE) {
+            mService.updateCpuStatsNow();
+            synchronized (mService.mProcessCpuTracker) {
+                cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
+            }
+            info.append(processCpuTracker.printCurrentLoad());
+            info.append(cpuInfo);
+        }
+
+        info.append(processCpuTracker.printCurrentState(anrTime));
+
+        Slog.e(TAG, info.toString());
+        if (tracesFile == null) {
+            // There is no trace file, so dump (only) the alleged culprit's threads to the log
+            Process.sendSignal(pid, Process.SIGNAL_QUIT);
+        }
+
+        StatsLog.write(StatsLog.ANR_OCCURRED, uid, processName,
+                activityShortComponentName == null ? "unknown": activityShortComponentName,
+                annotation,
+                (this.info != null) ? (this.info.isInstantApp()
+                        ? StatsLog.ANROCCURRED__IS_INSTANT_APP__TRUE
+                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__FALSE)
+                        : StatsLog.ANROCCURRED__IS_INSTANT_APP__UNAVAILABLE,
+                isInterestingToUserLocked()
+                        ? StatsLog.ANROCCURRED__FOREGROUND_STATE__FOREGROUND
+                        : StatsLog.ANROCCURRED__FOREGROUND_STATE__BACKGROUND);
+        final ProcessRecord parentPr = parentProcess != null
+                ? (ProcessRecord) parentProcess.mOwner : null;
+        mService.addErrorToDropBox("anr", this, processName, activityShortComponentName,
+                parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null);
+
+        if (mService.mActivityTaskManager.mController != null) {
+            try {
+                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
+                int res = mService.mActivityTaskManager.mController.appNotResponding(
+                        processName, pid, info.toString());
+                if (res != 0) {
+                    if (res < 0 && pid != MY_PID) {
+                        kill("anr", true);
+                    } else {
+                        synchronized (mService) {
+                            mService.mServices.scheduleServiceTimeoutLocked(this);
+                        }
+                    }
+                    return;
+                }
+            } catch (RemoteException e) {
+                mService.mActivityTaskManager.mController = null;
+                Watchdog.getInstance().setActivityController(null);
+            }
+        }
+
+        synchronized (mService) {
+            mService.mBatteryStatsService.noteProcessAnr(processName, uid);
+
+            if (isSilentANR) {
+                kill("bg anr", true);
+                return;
+            }
+
+            // Set the app's notResponding state, and look up the errorReportReceiver
+            makeAppNotRespondingLocked(activityShortComponentName,
+                    annotation != null ? "ANR " + annotation : "ANR", info.toString());
+
+            // Bring up the infamous App Not Responding dialog
+            Message msg = Message.obtain();
+            msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
+            msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
+
+            mService.mUiHandler.sendMessage(msg);
+        }
+    }
+
+    private void makeAppNotRespondingLocked(String activity, String shortMsg, String longMsg) {
+        setNotResponding(true);
+        notRespondingReport = mService.mAppErrors.generateProcessError(this,
+                ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING,
+                activity, shortMsg, longMsg, null);
+        startAppProblemLocked();
+        getWindowProcessController().stopFreezingActivities();
+    }
+
+    void startAppProblemLocked() {
+        // If this app is not running under the current user, then we can't give it a report button
+        // because that would require launching the report UI under a different user.
+        errorReportReceiver = null;
+
+        for (int userId : mService.mUserController.getCurrentProfileIds()) {
+            if (this.userId == userId) {
+                errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
+                        mService.mContext, info.packageName, info.flags);
+            }
+        }
+        mService.skipCurrentReceiverLocked(this);
+    }
+
+    private boolean isInterestingForBackgroundTraces() {
+        // The system_server is always considered interesting.
+        if (pid == MY_PID) {
+            return true;
+        }
+
+        // A package is considered interesting if any of the following is true :
+        //
+        // - It's displaying an activity.
+        // - It's the SystemUI.
+        // - It has an overlay or a top UI visible.
+        //
+        // NOTE: The check whether a given ProcessRecord belongs to the systemui
+        // process is a bit of a kludge, but the same pattern seems repeated at
+        // several places in the system server.
+        return isInterestingToUserLocked() ||
+                (info != null && "com.android.systemui".equals(info.packageName))
+                || (hasTopUi() || hasOverlayUi());
+    }
 }
diff --git a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
index eae28127..111adec 100644
--- a/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/am/TaskLaunchParamsModifier.java
@@ -114,6 +114,26 @@
     private int calculate(TaskRecord task, ActivityInfo.WindowLayout layout,
             ActivityRecord activity, ActivityRecord source, ActivityOptions options,
             LaunchParams currentParams, LaunchParams outParams) {
+        final ActivityRecord root;
+        if (task != null) {
+            root = task.getRootActivity() == null ? activity : task.getRootActivity();
+        } else {
+            root = activity;
+        }
+
+        // TODO: Investigate whether we can safely ignore all cases where we don't have root
+        // activity available. Note we can't know if the bounds are valid if we're not sure of the
+        // requested orientation of the root activity. Therefore if we found such a case we may need
+        // to pass the activity into this modifier in that case.
+        if (root == null) {
+            // There is a case that can lead us here. The caller is moving the top activity that is
+            // in a task that has multiple activities to PIP mode. For that the caller is creating a
+            // new task to host the activity so that we only move the top activity to PIP mode and
+            // keep other activities in the previous task. There is no point to apply the launch
+            // logic in this case.
+            return RESULT_SKIP;
+        }
+
         // STEP 1: Determine the display to launch the activity/task.
         final int displayId = getPreferredLaunchDisplay(options, source, currentParams);
         outParams.mPreferredDisplayId = displayId;
@@ -123,12 +143,6 @@
                     + display.getWindowingMode());
         }
 
-        final ActivityRecord root;
-        if (task != null) {
-            root = (task.getRootActivity() == null ? activity : task.getRootActivity());
-        } else {
-            root = activity;
-        }
         // STEP 2: Resolve launch windowing mode.
         // STEP 2.1: Determine if any parameter has specified initial bounds. That might be the
         // launch bounds from activity options, or size/gravity passed in layout. It also treats the
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 7e3893b..792b66b 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -30,6 +30,9 @@
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
 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;
@@ -44,6 +47,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import android.util.proto.ProtoOutputStream;
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.wm.ConfigurationContainer;
@@ -614,12 +618,19 @@
             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() {
+        synchronized (mAtm.mGlobalLock) {
+            return isInstrumenting() || isUsingWrapper()
+                    ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS : KEY_DISPATCHING_TIMEOUT_MS;
+        }
     }
 
     void clearProfilerIfNeeded() {
@@ -760,4 +771,9 @@
         pw.println(prefix + " mLastReportedConfiguration=" + mLastReportedConfiguration);
     }
 
+    void writeToProto(ProtoOutputStream proto, long fieldId) {
+        if (mListener != null) {
+            mListener.writeToProto(proto, fieldId);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/WindowProcessListener.java b/services/core/java/com/android/server/am/WindowProcessListener.java
index 2de3e37..9cad6fe4 100644
--- a/services/core/java/com/android/server/am/WindowProcessListener.java
+++ b/services/core/java/com/android/server/am/WindowProcessListener.java
@@ -16,6 +16,9 @@
 
 package com.android.server.am;
 
+import android.content.pm.ApplicationInfo;
+import android.util.proto.ProtoOutputStream;
+
 /**
  * Interface used by the owner/creator of a process that owns windows to listen to changes from the
  * WM side.
@@ -47,4 +50,6 @@
 
     /** Returns the total time (in milliseconds) spent executing in both user and system code. */
     long getCpuTime();
+
+    void writeToProto(ProtoOutputStream proto, long fieldId);
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cd1a7c2..f56d8e6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4682,22 +4682,15 @@
         }
     }
 
-    @Override
-    public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
-    {
-        mDeviceLogger.log((new AudioEventLogger.StringEvent(
-                "setHearingAidDeviceConnectionState state=" + state
-                        + " addr=" + device.getAddress())).printLog(TAG));
-
-        setBluetoothHearingAidDeviceConnectionState(
-                device, state,  false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
-    }
-
     public int setBluetoothHearingAidDeviceConnectionState(
             BluetoothDevice device, int state, boolean suppressNoisyIntent,
             int musicDevice)
     {
         int delay;
+        mDeviceLogger.log((new AudioEventLogger.StringEvent(
+                "setHearingAidDeviceConnectionState state=" + state
+                            + " addr=" + device.getAddress()
+                            + " supprNoisy=" + suppressNoisyIntent)).printLog(TAG));
         synchronized (mConnectedDevices) {
             if (!suppressNoisyIntent) {
                 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
@@ -5887,6 +5880,7 @@
                                    address));
         sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
                 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0);
+        setCurrentAudioRouteNameIfPossible(name);
     }
 
     private void onSendBecomingNoisyIntent() {
@@ -5908,7 +5902,7 @@
         mConnectedDevices.remove(
                 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
         // Remove A2DP routes as well
-        setCurrentAudioRouteName(null);
+        setCurrentAudioRouteNameIfPossible(null);
         if (mDockAddress == address) {
             mDockAddress = null;
         }
@@ -5978,6 +5972,7 @@
         sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
                             AudioSystem.DEVICE_OUT_HEARING_AID, 0,
                             mStreamStates[AudioSystem.STREAM_MUSIC], 0);
+        setCurrentAudioRouteNameIfPossible(name);
     }
 
     // must be called synchronized on mConnectedDevices
@@ -5987,7 +5982,7 @@
         mConnectedDevices.remove(
                 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
         // Remove Hearing Aid routes as well
-        setCurrentAudioRouteName(null);
+        setCurrentAudioRouteNameIfPossible(null);
     }
 
     // must be called synchronized on mConnectedDevices
@@ -6032,7 +6027,6 @@
                 } else {
                     makeA2dpDeviceUnavailableNow(address);
                 }
-                setCurrentAudioRouteName(null);
             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
                 if (btDevice.isBluetoothDock()) {
                     // this could be a reconnection after a transient disconnection
@@ -6056,7 +6050,6 @@
                 }
                 makeA2dpDeviceAvailable(address, btDevice.getName(),
                         "onSetA2dpSinkConnectionState");
-                setCurrentAudioRouteName(btDevice.getAliasName());
             }
         }
     }
@@ -6108,25 +6101,35 @@
 
             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
                 makeHearingAidDeviceUnavailable(address);
-                setCurrentAudioRouteName(null);
             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
                 makeHearingAidDeviceAvailable(address, btDevice.getName(),
                         "onSetHearingAidConnectionState");
-                setCurrentAudioRouteName(btDevice.getAliasName());
             }
         }
     }
 
-    private void setCurrentAudioRouteName(String name){
+    private void setCurrentAudioRouteNameIfPossible(String name) {
         synchronized (mCurAudioRoutes) {
             if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
-                mCurAudioRoutes.bluetoothName = name;
-                sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
-                        SENDMSG_NOOP, 0, 0, null, 0);
+                if (name != null || !isCurrentDeviceConnected()) {
+                    mCurAudioRoutes.bluetoothName = name;
+                    sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
+                            SENDMSG_NOOP, 0, 0, null, 0);
+                }
             }
         }
     }
 
+    private boolean isCurrentDeviceConnected() {
+        for (int i = 0; i < mConnectedDevices.size(); i++) {
+            DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
+            if (TextUtils.equals(deviceSpec.mDeviceName, mCurAudioRoutes.bluetoothName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
     {
         if (DEBUG_DEVICES) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index c16d3cd..b148a2f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -307,19 +307,19 @@
     private final class CecMessageBuffer {
         private List<HdmiCecMessage> mBuffer = new ArrayList<>();
 
-        public void bufferMessage(HdmiCecMessage message) {
+        public boolean bufferMessage(HdmiCecMessage message) {
             switch (message.getOpcode()) {
                 case Constants.MESSAGE_ACTIVE_SOURCE:
                     bufferActiveSource(message);
-                    break;
+                    return true;
                 case Constants.MESSAGE_IMAGE_VIEW_ON:
                 case Constants.MESSAGE_TEXT_VIEW_ON:
                     bufferImageOrTextViewOn(message);
-                    break;
+                    return true;
                     // Add here if new message that needs to buffer
                 default:
                     // Do not need to buffer messages other than above
-                    break;
+                    return false;
             }
         }
 
@@ -906,10 +906,6 @@
     @ServiceThreadOnly
     boolean handleCecCommand(HdmiCecMessage message) {
         assertRunOnServiceThread();
-        if (!mAddressAllocated) {
-            mCecMessageBuffer.bufferMessage(message);
-            return true;
-        }
         int errorCode = mMessageValidator.isValid(message);
         if (errorCode != HdmiCecMessageValidator.OK) {
             // We'll not response on the messages with the invalid source or destination
@@ -919,7 +915,12 @@
             }
             return true;
         }
-        return dispatchMessageToLocalDevice(message);
+
+        if (dispatchMessageToLocalDevice(message)) {
+            return true;
+        }
+
+        return (!mAddressAllocated) ? mCecMessageBuffer.bufferMessage(message) : false;
     }
 
     void enableAudioReturnChannel(int portId, boolean enabled) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index d347a91..f7e871d 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -50,8 +50,7 @@
             @Override
             public void onSendCompleted(int error) {
                 if (error != SendMessageResult.SUCCESS) {
-                    tv().setSystemAudioMode(false);
-                    finish();
+                    handleSystemAudioModeStatusTimeout();
                 }
             }
         });
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/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 862ea9d..fc76b46 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2015,10 +2015,6 @@
     }
 
     @Override
-    public void finishInput(IInputMethodClient client) {
-    }
-
-    @Override
     public void onServiceConnected(ComponentName name, IBinder service) {
         synchronized (mMethodMap) {
             if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 0a93653..e6a018a 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -31,9 +31,11 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
 import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
+import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.media.RingtoneManager;
@@ -1182,12 +1184,16 @@
             final int permissionGrantCount = permissionGrants.size();
             for (int j = 0; j < permissionGrantCount; j++) {
                 DefaultPermissionGrant permissionGrant = permissionGrants.get(j);
+                if (!isPermissionDangerous(permissionGrant.name)) {
+                    Log.w(TAG, "Ignoring permission " + permissionGrant.name
+                            + " which isn't dangerous");
+                    continue;
+                }
                 if (permissions == null) {
                     permissions = new ArraySet<>();
                 } else {
                     permissions.clear();
                 }
-                permissions.add(permissionGrant.name);
                 grantRuntimePermissions(pkg, permissions, permissionGrant.fixed, userId);
             }
         }
@@ -1350,6 +1356,16 @@
                 && pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
     }
 
+    private boolean isPermissionDangerous(String name) {
+        try {
+            final PermissionInfo pi = mContext.getPackageManager().getPermissionInfo(name, 0);
+            return (pi.getProtectionFlags() & PermissionInfo.PROTECTION_DANGEROUS) != 0;
+        } catch (NameNotFoundException e) {
+            // When unknown assume it's dangerous to be on the safe side
+            return true;
+        }
+    }
+
     private static final class DefaultPermissionGrant {
         final String name;
         final boolean fixed;
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 81a9ee0..7f9ee84 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -314,7 +314,6 @@
     public abstract boolean showStrictModeViolationDialog();
     public abstract void showSystemReadyErrorDialogsIfNeeded();
 
-    public abstract long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason);
     public abstract void onProcessMapped(int pid, WindowProcessController proc);
     public abstract void onProcessUnMapped(int pid);
 
@@ -431,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/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index eeb6f6a..10d77e5 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -125,7 +125,7 @@
         } else if (windowState != null) {
             // Notify the activity manager about the timeout and let it decide whether
             // to abort dispatching or keep waiting.
-            long timeout = mService.mAtmInternal.inputDispatchingTimedOut(
+            long timeout = mService.mAmInternal.inputDispatchingTimedOut(
                     windowState.mSession.mPid, aboveSystem, reason);
             if (timeout >= 0) {
                 // The activity manager declined to abort dispatching.
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 da6bfd1..056e92e 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);
@@ -3127,18 +3117,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/am/TaskLaunchParamsModifierTests.java b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index ea1320c..169204f 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -29,6 +29,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -97,6 +98,13 @@
         mResult.reset();
     }
 
+    @Test
+    public void testReturnsSkipWithEmptyActivity() {
+        final TaskRecord task = new TaskBuilder(mSupervisor).build();
+        assertEquals(RESULT_SKIP, mTarget.onCalculate(task, /* layout */ null,
+                /* activity */ null, /* source */ null, /* options */ null, mCurrent, mResult));
+    }
+
     // =============================
     // Display ID Related Tests
     // =============================
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..b0997f1 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1202,6 +1202,20 @@
             "always_show_data_rat_icon_bool";
 
     /**
+     * Boolean indicating if default data account should show LTE or 4G icon
+     * @hide
+     */
+    public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL =
+            "show_4g_for_lte_data_icon_bool";
+
+    /**
+     * Boolean indicating if lte+ icon should be shown if available
+     * @hide
+     */
+    public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL =
+            "hide_lte_plus_data_icon_bool";
+
+    /**
      * Boolean to decide whether to show precise call failed cause to user
      * @hide
      */
@@ -1965,6 +1979,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
      */
@@ -2505,6 +2544,8 @@
         sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
         sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, true);
+        sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
         sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
         sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
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/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index 8d18ae8..f2d0cbf 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -16,22 +16,19 @@
 
 package android.telephony.ims;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telecom.Log;
 import android.telephony.Rlog;
 
-/*
- * This file contains all the api's through which
- * information received in Dialog Event Package can be
- * queried
- */
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
- * Parcelable object to handle MultiEndpoint Dialog Information
+ * Parcelable object to handle MultiEndpoint Dialog Event Package Information.
  * @hide
  */
 @SystemApi
@@ -40,8 +37,39 @@
     private static final String TAG = "ImsExternalCallState";
 
     // Dialog States
+    /**
+     * The external call is in the confirmed dialog state.
+     */
     public static final int CALL_STATE_CONFIRMED = 1;
+    /**
+     * The external call is in the terminated dialog state.
+     */
     public static final int CALL_STATE_TERMINATED = 2;
+
+    /**@hide*/
+    @IntDef(flag = true,
+            value = {
+                    CALL_STATE_CONFIRMED,
+                    CALL_STATE_TERMINATED
+            },
+            prefix = "CALL_STATE_")
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ExternalCallState {}
+
+    /**@hide*/
+    @IntDef(flag = true,
+            value = {
+                    ImsCallProfile.CALL_TYPE_VOICE,
+                    ImsCallProfile.CALL_TYPE_VT_TX,
+                    ImsCallProfile.CALL_TYPE_VT_RX,
+                    ImsCallProfile.CALL_TYPE_VT
+            },
+            prefix = "CALL_TYPE_")
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ExternalCallType {}
+
+
+
     // Dialog Id
     private int mCallId;
     // Number
@@ -58,10 +86,9 @@
     public ImsExternalCallState() {
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
-            int callType, boolean isCallheld) {
+    /**@hide*/
+    public ImsExternalCallState(int callId, Uri address, boolean isPullable,
+            @ExternalCallState int callState, int callType, boolean isCallheld) {
         mCallId = callId;
         mAddress = address;
         mIsPullable = isPullable;
@@ -71,9 +98,10 @@
         Rlog.d(TAG, "ImsExternalCallState = " + this);
     }
 
-    /** @hide */
+    /**@hide*/
     public ImsExternalCallState(int callId, Uri address, Uri localAddress,
-            boolean isPullable, int callState, int callType, boolean isCallheld) {
+            boolean isPullable, @ExternalCallState int callState, int callType,
+            boolean isCallheld) {
         mCallId = callId;
         mAddress = address;
         mLocalAddress = localAddress;
@@ -84,6 +112,31 @@
         Rlog.d(TAG, "ImsExternalCallState = " + this);
     }
 
+    /**
+     * Create a new ImsExternalCallState instance to contain Multiendpoint Dialog information.
+     * @param callId The unique ID of the call, which will be used to identify this external
+     *               connection.
+     * @param address A {@link Uri} containing the remote address of this external connection.
+     * @param localAddress A {@link Uri} containing the local address information.
+     * @param isPullable A flag determining if this external connection can be pulled to the current
+     *         device.
+     * @param callState The state of the external call.
+     * @param callType The type of external call.
+     * @param isCallheld A flag determining if the external connection is currently held.
+     */
+    public ImsExternalCallState(String callId, Uri address, Uri localAddress,
+            boolean isPullable, @ExternalCallState int callState, @ExternalCallType int callType,
+            boolean isCallheld) {
+        mCallId = getIdForString(callId);
+        mAddress = address;
+        mLocalAddress = localAddress;
+        mIsPullable = isPullable;
+        mCallState = callState;
+        mCallType = callType;
+        mIsHeld = isCallheld;
+        Rlog.d(TAG, "ImsExternalCallState = " + this);
+    }
+
     /** @hide */
     public ImsExternalCallState(Parcel in) {
         mCallId = in.readInt();
@@ -135,7 +188,9 @@
         return mAddress;
     }
 
-    /** @hide */
+    /**
+     * @return A {@link Uri} containing the local address from the Multiendpoint Dialog Information.
+     */
     public Uri getLocalAddress() {
         return mLocalAddress;
     }
@@ -144,11 +199,11 @@
         return mIsPullable;
     }
 
-    public int getCallState() {
+    public @ExternalCallState int getCallState() {
         return mCallState;
     }
 
-    public int getCallType() {
+    public @ExternalCallType int getCallType() {
         return mCallType;
     }
 
@@ -166,4 +221,15 @@
                 ", mCallType = " + mCallType +
                 ", mIsHeld = " + mIsHeld + "}";
     }
+
+    private int getIdForString(String idString) {
+        try {
+            return Integer.parseInt(idString);
+        } catch (NumberFormatException e) {
+            // In the case that there are alphanumeric characters, we will create a hash of the
+            // String value as a backup.
+            // TODO: Modify call IDs to use Strings as keys instead of integers in telephony/telecom
+            return idString.hashCode();
+        }
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 86cb1b7..b0c875e 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -100,6 +100,7 @@
     public static final int EVENT_DATA_RECONNECT = BASE + 47;
     public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48;
     public static final int EVENT_DATA_SERVICE_BINDING_CHANGED = BASE + 49;
+    public static final int EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE = BASE + 50;
 
     /***** Constants *****/
 
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/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp
index a20b9b7..b353ff0 100644
--- a/tools/aapt2/LoadedApk.cpp
+++ b/tools/aapt2/LoadedApk.cpp
@@ -35,6 +35,43 @@
 
 namespace aapt {
 
+static ApkFormat DetermineApkFormat(io::IFileCollection* apk) {
+  if (apk->FindFile(kApkResourceTablePath) != nullptr) {
+    return ApkFormat::kBinary;
+  } else if (apk->FindFile(kProtoResourceTablePath) != nullptr) {
+    return ApkFormat::kProto;
+  } else {
+    // If the resource table is not present, attempt to read the manifest.
+    io::IFile* manifest_file = apk->FindFile(kAndroidManifestPath);
+    if (manifest_file == nullptr) {
+      return ApkFormat::kUnknown;
+    }
+
+    // First try in proto format.
+    std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream();
+    if (manifest_in != nullptr) {
+      pb::XmlNode pb_node;
+      io::ProtoInputStreamReader proto_reader(manifest_in.get());
+      if (proto_reader.ReadMessage(&pb_node)) {
+        return ApkFormat::kProto;
+      }
+    }
+
+    // If it didn't work, try in binary format.
+    std::unique_ptr<io::IData> manifest_data = manifest_file->OpenAsData();
+    if (manifest_data != nullptr) {
+      std::string error;
+      std::unique_ptr<xml::XmlResource> manifest =
+          xml::Inflate(manifest_data->data(), manifest_data->size(), &error);
+      if (manifest != nullptr) {
+        return ApkFormat::kBinary;
+      }
+    }
+
+    return ApkFormat::kUnknown;
+  }
+}
+
 std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, IDiagnostics* diag) {
   Source source(path);
   std::string error;
@@ -301,41 +338,4 @@
   return doc;
 }
 
-ApkFormat LoadedApk::DetermineApkFormat(io::IFileCollection* apk) {
-  if (apk->FindFile(kApkResourceTablePath) != nullptr) {
-    return ApkFormat::kBinary;
-  } else if (apk->FindFile(kProtoResourceTablePath) != nullptr) {
-    return ApkFormat::kProto;
-  } else {
-    // If the resource table is not present, attempt to read the manifest.
-    io::IFile* manifest_file = apk->FindFile(kAndroidManifestPath);
-    if (manifest_file == nullptr) {
-      return ApkFormat::kUnknown;
-    }
-
-    // First try in proto format.
-    std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream();
-    if (manifest_in != nullptr) {
-      pb::XmlNode pb_node;
-      io::ProtoInputStreamReader proto_reader(manifest_in.get());
-      if (!proto_reader.ReadMessage(&pb_node)) {
-        return ApkFormat::kProto;
-      }
-    }
-
-    // If it didn't work, try in binary format.
-    std::unique_ptr<io::IData> manifest_data = manifest_file->OpenAsData();
-    if (manifest_data != nullptr) {
-      std::string error;
-      std::unique_ptr<xml::XmlResource> manifest =
-          xml::Inflate(manifest_data->data(), manifest_data->size(), &error);
-      if (manifest != nullptr) {
-        return ApkFormat::kBinary;
-      }
-    }
-
-    return ApkFormat::kUnknown;
-  }
-}
-
 }  // namespace aapt
diff --git a/tools/aapt2/LoadedApk.h b/tools/aapt2/LoadedApk.h
index 84c57c1..5b6f45e 100644
--- a/tools/aapt2/LoadedApk.h
+++ b/tools/aapt2/LoadedApk.h
@@ -121,8 +121,6 @@
   std::unique_ptr<ResourceTable> table_;
   std::unique_ptr<xml::XmlResource> manifest_;
   ApkFormat format_;
-
-  static ApkFormat DetermineApkFormat(io::IFileCollection* apk);
 };
 
 }  // namespace aapt
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)
+
+