Merge "Remove RRO policy product_services"
diff --git a/Android.bp b/Android.bp
index c202408..54b6619 100644
--- a/Android.bp
+++ b/Android.bp
@@ -305,6 +305,7 @@
         "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
         "core/java/android/service/gatekeeper/IGateKeeperService.aidl",
         "core/java/android/service/contentcapture/IContentCaptureService.aidl",
+        "core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl",
         "core/java/android/service/notification/INotificationListener.aidl",
         "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
         "core/java/android/service/notification/IConditionListener.aidl",
@@ -476,6 +477,7 @@
         "media/java/android/media/IMediaRouterClient.aidl",
         "media/java/android/media/IMediaRouterService.aidl",
         "media/java/android/media/IMediaSession2.aidl",
+        "media/java/android/media/IMediaSession2Service.aidl",
         "media/java/android/media/IMediaScannerListener.aidl",
         "media/java/android/media/IMediaScannerService.aidl",
         "media/java/android/media/IPlaybackConfigDispatcher.aidl",
@@ -887,7 +889,12 @@
         "core/java/android/net/IIpMemoryStore.aidl",
         "core/java/android/net/INetworkStackConnector.aidl",
         "core/java/android/net/INetworkStackStatusCallback.aidl",
+        "core/java/android/net/IpPrefixParcelable.aidl",
+        "core/java/android/net/LinkAddressParcelable.aidl",
+        "core/java/android/net/LinkPropertiesParcelable.aidl",
         "core/java/android/net/PrivateDnsConfigParcel.aidl",
+        "core/java/android/net/ProxyInfoParcelable.aidl",
+        "core/java/android/net/RouteInfoParcelable.aidl",
         "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl",
         "core/java/android/net/dhcp/IDhcpServer.aidl",
         "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
@@ -1317,7 +1324,6 @@
         "ext",
         "framework",
         "voip-common",
-        "android.test.mock.impl",
     ],
     local_sourcepaths: frameworks_base_subdirs,
     installable: false,
diff --git a/api/current.txt b/api/current.txt
index e2ea649..b5b47b0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6784,9 +6784,11 @@
     method public void wipeData(int);
     method public void wipeData(int, java.lang.CharSequence);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
+    field public static final java.lang.String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE";
     field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
     field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
+    field public static final java.lang.String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE";
     field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
     field public static final java.lang.String ACTION_PROFILE_OWNER_CHANGED = "android.app.action.PROFILE_OWNER_CHANGED";
     field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";
@@ -6829,12 +6831,15 @@
     field public static final java.lang.String EXTRA_PROVISIONING_DISCLAIMER_CONTENT = "android.app.extra.PROVISIONING_DISCLAIMER_CONTENT";
     field public static final java.lang.String EXTRA_PROVISIONING_DISCLAIMER_HEADER = "android.app.extra.PROVISIONING_DISCLAIMER_HEADER";
     field public static final deprecated java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+    field public static final java.lang.String EXTRA_PROVISIONING_IMEI = "android.app.extra.PROVISIONING_IMEI";
     field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION";
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
     field public static final java.lang.String EXTRA_PROVISIONING_LOGO_URI = "android.app.extra.PROVISIONING_LOGO_URI";
     field public static final java.lang.String EXTRA_PROVISIONING_MAIN_COLOR = "android.app.extra.PROVISIONING_MAIN_COLOR";
+    field public static final java.lang.String EXTRA_PROVISIONING_MODE = "android.app.extra.PROVISIONING_MODE";
+    field public static final java.lang.String EXTRA_PROVISIONING_SERIAL_NUMBER = "android.app.extra.PROVISIONING_SERIAL_NUMBER";
     field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
     field public static final java.lang.String EXTRA_PROVISIONING_SKIP_USER_CONSENT = "android.app.extra.PROVISIONING_SKIP_USER_CONSENT";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -6911,6 +6916,9 @@
     field public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2; // 0x2
     field public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1; // 0x1
     field public static final int PRIVATE_DNS_SET_SUCCESS = 0; // 0x0
+    field public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE = 1; // 0x1
+    field public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2; // 0x2
+    field public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 3; // 0x3
     field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
@@ -7682,6 +7690,7 @@
     field public static final int ACTIVITY_RESUMED = 1; // 0x1
     field public static final int ACTIVITY_STOPPED = 23; // 0x17
     field public static final int CONFIGURATION_CHANGE = 5; // 0x5
+    field public static final int DEVICE_SHUTDOWN = 26; // 0x1a
     field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
     field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
     field public static final int KEYGUARD_HIDDEN = 18; // 0x12
@@ -12281,6 +12290,7 @@
     method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException;
     method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics);
+    field public static final int ID_NULL = 0; // 0x0
   }
 
   public static class Resources.NotFoundException extends java.lang.RuntimeException {
@@ -12324,6 +12334,7 @@
     method public java.lang.String getPositionDescription();
     method public int getResourceId(int, int);
     method public android.content.res.Resources getResources();
+    method public int getSourceStyleResourceId(int, int);
     method public java.lang.String getString(int);
     method public java.lang.CharSequence getText(int);
     method public java.lang.CharSequence[] getTextArray(int);
@@ -16457,9 +16468,9 @@
 
   public class BiometricManager {
     method public int canAuthenticate();
-    field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
+    field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
+    field public static final int BIOMETRIC_ERROR_NONE_ENROLLED = 11; // 0xb
     field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
-    field public static final int BIOMETRIC_ERROR_UNAVAILABLE = 1; // 0x1
     field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
   }
 
@@ -16502,6 +16513,7 @@
     method public android.hardware.biometrics.BiometricPrompt build();
     method public android.hardware.biometrics.BiometricPrompt.Builder setDescription(java.lang.CharSequence);
     method public android.hardware.biometrics.BiometricPrompt.Builder setNegativeButton(java.lang.CharSequence, java.util.concurrent.Executor, android.content.DialogInterface.OnClickListener);
+    method public android.hardware.biometrics.BiometricPrompt.Builder setRequireConfirmation(boolean);
     method public android.hardware.biometrics.BiometricPrompt.Builder setSubtitle(java.lang.CharSequence);
     method public android.hardware.biometrics.BiometricPrompt.Builder setTitle(java.lang.CharSequence);
   }
@@ -24135,6 +24147,7 @@
     method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
     method protected void finalize();
     method public void flush();
+    method public java.lang.String getCanonicalName();
     method public android.media.MediaCodecInfo getCodecInfo();
     method public java.nio.ByteBuffer getInputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
@@ -24261,10 +24274,15 @@
   }
 
   public final class MediaCodecInfo {
+    method public java.lang.String getCanonicalName();
     method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String);
     method public java.lang.String getName();
     method public java.lang.String[] getSupportedTypes();
+    method public boolean isAlias();
     method public boolean isEncoder();
+    method public boolean isHardwareAccelerated();
+    method public boolean isSoftwareOnly();
+    method public boolean isVendor();
   }
 
   public static final class MediaCodecInfo.AudioCapabilities {
@@ -24340,7 +24358,10 @@
     field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
     field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
     field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback";
+    field public static final java.lang.String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+    field public static final java.lang.String FEATURE_FrameParsing = "frame-parsing";
     field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh";
+    field public static final java.lang.String FEATURE_MultipleFrames = "multiple-frames";
     field public static final java.lang.String FEATURE_PartialFrame = "partial-frame";
     field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback";
     field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback";
@@ -24362,6 +24383,33 @@
     field public static final int AACObjectSSR = 3; // 0x3
     field public static final int AACObjectScalable = 6; // 0x6
     field public static final int AACObjectXHE = 42; // 0x2a
+    field public static final int AV1Level2 = 1; // 0x1
+    field public static final int AV1Level21 = 2; // 0x2
+    field public static final int AV1Level22 = 4; // 0x4
+    field public static final int AV1Level23 = 8; // 0x8
+    field public static final int AV1Level3 = 16; // 0x10
+    field public static final int AV1Level31 = 32; // 0x20
+    field public static final int AV1Level32 = 64; // 0x40
+    field public static final int AV1Level33 = 128; // 0x80
+    field public static final int AV1Level4 = 256; // 0x100
+    field public static final int AV1Level41 = 512; // 0x200
+    field public static final int AV1Level42 = 1024; // 0x400
+    field public static final int AV1Level43 = 2048; // 0x800
+    field public static final int AV1Level5 = 4096; // 0x1000
+    field public static final int AV1Level51 = 8192; // 0x2000
+    field public static final int AV1Level52 = 16384; // 0x4000
+    field public static final int AV1Level53 = 32768; // 0x8000
+    field public static final int AV1Level6 = 65536; // 0x10000
+    field public static final int AV1Level61 = 131072; // 0x20000
+    field public static final int AV1Level62 = 262144; // 0x40000
+    field public static final int AV1Level63 = 524288; // 0x80000
+    field public static final int AV1Level7 = 1048576; // 0x100000
+    field public static final int AV1Level71 = 2097152; // 0x200000
+    field public static final int AV1Level72 = 4194304; // 0x400000
+    field public static final int AV1Level73 = 8388608; // 0x800000
+    field public static final int AV1Profile0 = 1; // 0x1
+    field public static final int AV1Profile1 = 2; // 0x2
+    field public static final int AV1Profile2 = 4; // 0x4
     field public static final int AVCLevel1 = 1; // 0x1
     field public static final int AVCLevel11 = 4; // 0x4
     field public static final int AVCLevel12 = 8; // 0x8
@@ -24379,6 +24427,9 @@
     field public static final int AVCLevel5 = 16384; // 0x4000
     field public static final int AVCLevel51 = 32768; // 0x8000
     field public static final int AVCLevel52 = 65536; // 0x10000
+    field public static final int AVCLevel6 = 131072; // 0x20000
+    field public static final int AVCLevel61 = 262144; // 0x40000
+    field public static final int AVCLevel62 = 524288; // 0x80000
     field public static final int AVCProfileBaseline = 1; // 0x1
     field public static final int AVCProfileConstrainedBaseline = 65536; // 0x10000
     field public static final int AVCProfileConstrainedHigh = 524288; // 0x80000
@@ -24541,12 +24592,53 @@
     method public android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int);
     method public android.util.Range<java.lang.Integer> getSupportedHeights();
     method public android.util.Range<java.lang.Integer> getSupportedHeightsFor(int);
+    method public java.util.List<android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint> getSupportedPerformancePoints();
     method public android.util.Range<java.lang.Integer> getSupportedWidths();
     method public android.util.Range<java.lang.Integer> getSupportedWidthsFor(int);
     method public int getWidthAlignment();
     method public boolean isSizeSupported(int, int);
   }
 
+  public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+    method public boolean covers(android.media.MediaFormat);
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
+    field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
+    field public final int frameRate;
+    field public final int height;
+    field public final int width;
+  }
+
   public final class MediaCodecList {
     ctor public MediaCodecList(int);
     method public java.lang.String findDecoderForFormat(android.media.MediaFormat);
@@ -24999,6 +25091,7 @@
     field public static final java.lang.String MIMETYPE_TEXT_CEA_708 = "text/cea-708";
     field public static final java.lang.String MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
     field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt";
+    field public static final java.lang.String MIMETYPE_VIDEO_AV1 = "video/av01";
     field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc";
     field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision";
     field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp";
@@ -25704,6 +25797,7 @@
     field public static final int VOICE_CALL = 4; // 0x4
     field public static final int VOICE_COMMUNICATION = 7; // 0x7
     field public static final int VOICE_DOWNLINK = 3; // 0x3
+    field public static final int VOICE_PERFORMANCE = 10; // 0xa
     field public static final int VOICE_RECOGNITION = 6; // 0x6
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
@@ -29819,7 +29913,7 @@
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
     method public int getMaxNumberOfNetworkSuggestionsPerApp();
-    method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
+    method public deprecated java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
     method public boolean is5GHzBandSupported();
@@ -29839,7 +29933,7 @@
     method public deprecated boolean reconnect();
     method public deprecated boolean removeNetwork(int);
     method public int removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
-    method public void removePasspointConfiguration(java.lang.String);
+    method public deprecated void removePasspointConfiguration(java.lang.String);
     method public deprecated boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -41735,6 +41829,7 @@
     field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10
     field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
     field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
+    field public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 128; // 0x80
     field public static final int SHOW_SOURCE_NOTIFICATION = 64; // 0x40
     field public static final int SHOW_SOURCE_PUSH_TO_TALK = 32; // 0x20
     field public static final int SHOW_WITH_ASSIST = 1; // 0x1
@@ -48251,6 +48346,7 @@
     field public int data;
     field public int density;
     field public int resourceId;
+    field public int sourceStyleResourceId;
     field public java.lang.CharSequence string;
     field public int type;
   }
@@ -53012,19 +53108,8 @@
     ctor public InspectionCompanion.UninitializedPropertyMapException();
   }
 
-  public final class IntEnumMapping {
-    method public java.lang.String nameOf(int);
-  }
-
-  public static final class IntEnumMapping.Builder {
-    ctor public IntEnumMapping.Builder();
-    method public android.view.inspector.IntEnumMapping.Builder addValue(java.lang.String, int);
-    method public android.view.inspector.IntEnumMapping build();
-    method public void clear();
-  }
-
   public final class IntFlagMapping {
-    method public java.lang.String[] namesOf(int);
+    method public java.util.Set<java.lang.String> get(int);
   }
 
   public static final class IntFlagMapping.Builder {
@@ -53032,7 +53117,6 @@
     method public android.view.inspector.IntFlagMapping.Builder addFlag(java.lang.String, int);
     method public android.view.inspector.IntFlagMapping.Builder addFlag(java.lang.String, int, int);
     method public android.view.inspector.IntFlagMapping build();
-    method public void clear();
   }
 
   public abstract interface PropertyMapper {
@@ -53044,7 +53128,7 @@
     method public abstract int mapFloat(java.lang.String, int);
     method public abstract int mapGravity(java.lang.String, int);
     method public abstract int mapInt(java.lang.String, int);
-    method public abstract int mapIntEnum(java.lang.String, int, android.view.inspector.IntEnumMapping);
+    method public abstract int mapIntEnum(java.lang.String, int, android.util.SparseArray<java.lang.String>);
     method public abstract int mapIntFlag(java.lang.String, int, android.view.inspector.IntFlagMapping);
     method public abstract int mapLong(java.lang.String, int);
     method public abstract int mapObject(java.lang.String, int);
@@ -54251,6 +54335,8 @@
     method public static java.lang.ClassLoader getWebViewClassLoader();
     method public android.webkit.WebViewClient getWebViewClient();
     method public android.os.Looper getWebViewLooper();
+    method public android.webkit.WebViewRenderer getWebViewRenderer();
+    method public android.webkit.WebViewRendererClient getWebViewRendererClient();
     method public void goBack();
     method public void goBackOrForward(int);
     method public void goForward();
@@ -54300,6 +54386,8 @@
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
     method public void setWebViewClient(android.webkit.WebViewClient);
+    method public void setWebViewRendererClient(java.util.concurrent.Executor, android.webkit.WebViewRendererClient);
+    method public void setWebViewRendererClient(android.webkit.WebViewRendererClient);
     method public deprecated boolean shouldDelayChildPressedState();
     method public deprecated boolean showFindDialog(java.lang.String, boolean);
     method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>);
@@ -54415,6 +54503,16 @@
     method public android.webkit.WebView getWebView();
   }
 
+  public abstract class WebViewRenderer {
+    method public abstract boolean terminate();
+  }
+
+  public abstract class WebViewRendererClient {
+    ctor public WebViewRendererClient();
+    method public abstract void onRendererResponsive(android.webkit.WebView, android.webkit.WebViewRenderer);
+    method public abstract void onRendererUnresponsive(android.webkit.WebView, android.webkit.WebViewRenderer);
+  }
+
 }
 
 package android.widget {
diff --git a/api/system-current.txt b/api/system-current.txt
index 5fac1ee..dc5d266 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -94,7 +94,6 @@
     field public static final java.lang.String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
     field public static final java.lang.String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
     field public static final java.lang.String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
-    field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
     field public static final java.lang.String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
@@ -129,6 +128,7 @@
     field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
     field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
+    field public static final java.lang.String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
     field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
     field public static final java.lang.String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
     field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
@@ -151,6 +151,7 @@
     field public static final java.lang.String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
     field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
     field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
+    field public static final java.lang.String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
     field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
     field public static final java.lang.String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
     field public static final java.lang.String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
@@ -184,6 +185,7 @@
     field public static final java.lang.String UPDATE_TIME_ZONE_RULES = "android.permission.UPDATE_TIME_ZONE_RULES";
     field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
     field public static final java.lang.String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK";
+    field public static final java.lang.String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
     field public static final java.lang.String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE";
     field public static final java.lang.String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
     field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
@@ -195,6 +197,7 @@
   }
 
   public static final class R.array {
+    field public static final int config_defaultRoleHolders = 17235974; // 0x1070006
     field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
   }
 
@@ -1559,6 +1562,7 @@
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     field public static final int FLAG_REMOVED = 2; // 0x2
+    field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
     field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
@@ -3301,6 +3305,7 @@
   }
 
   public final class MediaRecorder.AudioSource {
+    field public static final int ECHO_REFERENCE = 1997; // 0x7cd
     field public static final int HOTWORD = 1999; // 0x7cf
     field public static final int RADIO_TUNER = 1998; // 0x7ce
   }
@@ -4139,12 +4144,19 @@
     field public static final int WPA2_PSK = 4; // 0x4
   }
 
+  public class WifiInfo implements android.os.Parcelable {
+    method public boolean isOsuAp();
+  }
+
   public class WifiManager {
     method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
     method public void connect(int, android.net.wifi.WifiManager.ActionListener);
     method public void disable(int, android.net.wifi.WifiManager.ActionListener);
     method public void disableEphemeralNetwork(java.lang.String);
     method public void forget(int, android.net.wifi.WifiManager.ActionListener);
+    method public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration, java.util.Map<java.lang.Integer, java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
+    method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
+    method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
     method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
     method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
     method public int getWifiApState();
@@ -4159,6 +4171,7 @@
     method public void startEasyConnectAsConfiguratorInitiator(java.lang.String, int, int, android.os.Handler, android.net.wifi.EasyConnectStatusCallback);
     method public void startEasyConnectAsEnrolleeInitiator(java.lang.String, android.os.Handler, android.net.wifi.EasyConnectStatusCallback);
     method public boolean startScan(android.os.WorkSource);
+    method public void startSubscriptionProvisioning(android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.ProvisioningCallback, android.os.Handler);
     method public void stopEasyConnectSession();
     method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
@@ -4178,6 +4191,8 @@
     field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
     field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
     field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
+    field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0
+    field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1
     field public static final java.lang.String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
     field public static final int WIFI_AP_STATE_DISABLED = 11; // 0xb
     field public static final int WIFI_AP_STATE_DISABLING = 10; // 0xa
@@ -4354,6 +4369,59 @@
 
 }
 
+package android.net.wifi.hotspot2 {
+
+  public final class OsuProvider implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getFriendlyName();
+    method public android.net.Uri getServerUri();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.OsuProvider> CREATOR;
+  }
+
+  public abstract class ProvisioningCallback {
+    ctor public ProvisioningCallback();
+    method public abstract void onProvisioningComplete();
+    method public abstract void onProvisioningFailure(int);
+    method public abstract void onProvisioningStatus(int);
+    field public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; // 0x16
+    field public static final int OSU_FAILURE_AP_CONNECTION = 1; // 0x1
+    field public static final int OSU_FAILURE_INVALID_SERVER_URL = 8; // 0x8
+    field public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; // 0x11
+    field public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; // 0x15
+    field public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; // 0xe
+    field public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; // 0x13
+    field public static final int OSU_FAILURE_NO_PPS_MO = 16; // 0x10
+    field public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; // 0x12
+    field public static final int OSU_FAILURE_OSU_PROVIDER_NOT_FOUND = 23; // 0x17
+    field public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6; // 0x6
+    field public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; // 0x7
+    field public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; // 0x14
+    field public static final int OSU_FAILURE_SERVER_CONNECTION = 3; // 0x3
+    field public static final int OSU_FAILURE_SERVER_URL_INVALID = 2; // 0x2
+    field public static final int OSU_FAILURE_SERVER_VALIDATION = 4; // 0x4
+    field public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; // 0x5
+    field public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; // 0xb
+    field public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12; // 0xc
+    field public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; // 0xd
+    field public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; // 0x9
+    field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; // 0xf
+    field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; // 0xa
+    field public static final int OSU_STATUS_AP_CONNECTED = 2; // 0x2
+    field public static final int OSU_STATUS_AP_CONNECTING = 1; // 0x1
+    field public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6; // 0x6
+    field public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8; // 0x8
+    field public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11; // 0xb
+    field public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9; // 0x9
+    field public static final int OSU_STATUS_SERVER_CONNECTED = 5; // 0x5
+    field public static final int OSU_STATUS_SERVER_CONNECTING = 3; // 0x3
+    field public static final int OSU_STATUS_SERVER_VALIDATED = 4; // 0x4
+    field public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10; // 0xa
+    field public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7; // 0x7
+  }
+
+}
+
 package android.net.wifi.rtt {
 
   public static final class RangingRequest.Builder {
@@ -4445,6 +4513,10 @@
     method public abstract java.lang.Object onTransactStarted(android.os.IBinder, int);
   }
 
+  public static class Build.VERSION {
+    field public static final java.lang.String PREVIEW_SDK_FINGERPRINT;
+  }
+
   public final class ConfigUpdate {
     field public static final java.lang.String ACTION_UPDATE_CARRIER_ID_DB = "android.os.action.UPDATE_CARRIER_ID_DB";
     field public static final java.lang.String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
@@ -4864,6 +4936,7 @@
     method public abstract int onCountPermissionApps(java.util.List<java.lang.String>, boolean, boolean);
     method public abstract java.util.List<android.permission.RuntimePermissionPresentationInfo> onGetAppPermissions(java.lang.String);
     method public abstract void onGetRuntimePermissionsBackup(android.os.UserHandle, java.io.OutputStream);
+    method public abstract java.util.List<android.permission.RuntimePermissionUsageInfo> onPermissionUsageResult(boolean, long);
     method public abstract void onRevokeRuntimePermission(java.lang.String, java.lang.String);
     method public abstract java.util.Map<java.lang.String, java.util.List<java.lang.String>> onRevokeRuntimePermissions(java.util.Map<java.lang.String, java.util.List<java.lang.String>>, boolean, int, java.lang.String);
     field public static final java.lang.String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
@@ -4892,11 +4965,12 @@
   public final class RuntimePermissionUsageInfo implements android.os.Parcelable {
     ctor public RuntimePermissionUsageInfo(java.lang.CharSequence, int);
     method public int describeContents();
-    method public java.lang.CharSequence getName();
     method public int getAppAccessCount();
+    method public java.lang.CharSequence getName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.permission.RuntimePermissionUsageInfo> CREATOR;
   }
+
 }
 
 package android.permissionpresenterservice {
@@ -5018,6 +5092,7 @@
     method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
     method public static void resetToDefaults(int, java.lang.String);
     method public static boolean setProperty(java.lang.String, java.lang.String, java.lang.String, boolean);
+    field public static final java.lang.String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final java.lang.String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
   }
 
@@ -7180,6 +7255,7 @@
     method public int getServiceType();
     method public static int getVideoStateFromCallType(int);
     method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+    method public boolean isEmergencyCallTesting();
     method public boolean isVideoCall();
     method public boolean isVideoPaused();
     method public static int presentationToOir(int);
@@ -7188,6 +7264,7 @@
     method public void setCallExtraInt(java.lang.String, int);
     method public void setCallRestrictCause(int);
     method public void setEmergencyCallRouting(int);
+    method public void setEmergencyCallTesting(boolean);
     method public void setEmergencyServiceCategories(int);
     method public void setEmergencyUrns(java.util.List<java.lang.String>);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
@@ -7252,7 +7329,6 @@
     method public void callSessionInviteParticipantsRequestDelivered();
     method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionMayHandover(int, int);
-    method public void callSessionRttAudioIndicatorChanged(android.telephony.ims.ImsStreamMediaProfile);
     method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
     method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
@@ -7263,6 +7339,7 @@
     method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
     method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
     method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+    method public void callSessionRttAudioIndicatorChanged(android.telephony.ims.ImsStreamMediaProfile);
     method public void callSessionRttMessageReceived(java.lang.String);
     method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
     method public void callSessionRttModifyResponseReceived(int);
@@ -8493,6 +8570,8 @@
     method public abstract int getVisibleTitleHeight();
     method public abstract android.webkit.WebChromeClient getWebChromeClient();
     method public abstract android.webkit.WebViewClient getWebViewClient();
+    method public abstract android.webkit.WebViewRenderer getWebViewRenderer();
+    method public abstract android.webkit.WebViewRendererClient getWebViewRendererClient();
     method public abstract android.view.View getZoomControls();
     method public abstract void goBack();
     method public abstract void goBackOrForward(int);
@@ -8542,6 +8621,7 @@
     method public abstract void setVerticalScrollbarOverlay(boolean);
     method public abstract void setWebChromeClient(android.webkit.WebChromeClient);
     method public abstract void setWebViewClient(android.webkit.WebViewClient);
+    method public abstract void setWebViewRendererClient(java.util.concurrent.Executor, android.webkit.WebViewRendererClient);
     method public abstract boolean showFindDialog(java.lang.String, boolean);
     method public abstract void stopLoading();
     method public abstract boolean zoomBy(float);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 4beb699..5a7ec8b 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -1,3 +1,11 @@
+package android {
+
+  public static final class Manifest.permission {
+    field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
+  }
+
+}
+
 package android.app {
 
   public class Notification implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index fb50fa19..e0e0f35 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -420,6 +420,7 @@
   }
 
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
     field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
@@ -509,6 +510,11 @@
     method public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, java.io.InputStream, int);
   }
 
+  public class Paint {
+    method public void setColor(long);
+    method public void setShadowLayer(float, float, float, long);
+  }
+
 }
 
 package android.graphics.drawable {
@@ -574,6 +580,8 @@
 
   public final class BrightnessConfiguration implements android.os.Parcelable {
     method public int describeContents();
+    method public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
+    method public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(java.lang.String);
     method public android.util.Pair<float[], float[]> getCurve();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
@@ -581,10 +589,22 @@
 
   public static class BrightnessConfiguration.Builder {
     ctor public BrightnessConfiguration.Builder(float[], float[]);
+    method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection);
+    method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(java.lang.String, android.hardware.display.BrightnessCorrection);
     method public android.hardware.display.BrightnessConfiguration build();
+    method public int getMaxCorrectionsByCategory();
+    method public int getMaxCorrectionsByPackageName();
     method public android.hardware.display.BrightnessConfiguration.Builder setDescription(java.lang.String);
   }
 
+  public final class BrightnessCorrection implements android.os.Parcelable {
+    method public float apply(float);
+    method public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR;
+  }
+
   public final class DisplayManager {
     method public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats();
     method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
@@ -945,6 +965,11 @@
     field public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
+  public final class MessageQueue {
+    method public int postSyncBarrier();
+    method public void removeSyncBarrier(int);
+  }
+
   public final class NativeHandle implements java.io.Closeable {
     ctor public NativeHandle();
     ctor public NativeHandle(java.io.FileDescriptor, boolean);
@@ -957,11 +982,6 @@
     method public boolean hasSingleFileDescriptor();
   }
 
-  public final class MessageQueue {
-    method public int postSyncBarrier();
-    method public void removeSyncBarrier(int);
-  }
-
   public final class PowerManager {
     method public int getPowerSaveMode();
     method public boolean setDynamicPowerSavings(boolean, int);
@@ -1098,6 +1118,24 @@
     field public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
   }
 
+  public class VintfObject {
+    method public static java.lang.String[] getHalNamesAndVersions();
+    method public static java.lang.String getSepolicyVersion();
+    method public static java.lang.Long getTargetFrameworkCompatibilityMatrixVersion();
+    method public static java.util.Map<java.lang.String, java.lang.String[]> getVndkSnapshots();
+    method public static java.lang.String[] report();
+  }
+
+  public class VintfRuntimeInfo {
+    method public static java.lang.String getCpuInfo();
+    method public static java.lang.String getHardwareId();
+    method public static java.lang.String getKernelVersion();
+    method public static java.lang.String getNodeName();
+    method public static java.lang.String getOsName();
+    method public static java.lang.String getOsRelease();
+    method public static java.lang.String getOsVersion();
+  }
+
   public class WorkSource implements android.os.Parcelable {
     ctor public WorkSource(int);
     method public boolean add(int);
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index e9cfe63..803f83c 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -20,6 +20,7 @@
         "misc-*",
         "modernize-*",
         "readability-*",
+        "-modernize-avoid-c-arrays",
     ],
     tidy_flags: [
         "-system-headers",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index f4a1715..7e2df27 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -25,6 +25,8 @@
 import "frameworks/base/core/proto/android/app/settings_enums.proto";
 import "frameworks/base/core/proto/android/app/job/enums.proto";
 import "frameworks/base/core/proto/android/bluetooth/enums.proto";
+import "frameworks/base/core/proto/android/bluetooth/hci/enums.proto";
+import "frameworks/base/core/proto/android/bluetooth/hfp/enums.proto";
 import "frameworks/base/core/proto/android/net/networkcapabilities.proto";
 import "frameworks/base/core/proto/android/os/enums.proto";
 import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto";
@@ -183,6 +185,9 @@
         RescuePartyResetReported rescue_party_reset_reported = 122;
         SignedConfigReported signed_config_reported = 123;
         GnssNiEventReported gnss_ni_event_reported = 124;
+        BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125;
+        BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126;
+        BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127;
     }
 
     // Pulled events will start at field 10000.
@@ -1298,10 +1303,12 @@
 }
 
 /**
- * Logs when a Bluetooth device connects and disconnects.
+ * Logs when profiles on a Bluetooth device connects and disconnects.
  *
  * Logged from:
- *    packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
+ *    packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java
+ *
+ * Next Tag: 5
  */
 message BluetoothConnectionStateChanged {
     // The state of the connection.
@@ -1310,13 +1317,152 @@
     // An identifier that can be used to match connect and disconnect events.
     // Currently is last two bytes of a hash of a device level ID and
     // the mac address of the bluetooth device that is connected.
-    optional int32 obfuscated_id = 2;
+    // Deprecated: use obfuscated_id instead, this one is always 0 for Q+
+    optional int32 OBSOLETE_obfuscated_id = 2 [deprecated = true];
     // The profile that is connected. Eg. GATT, A2DP, HEADSET.
     // From android.bluetooth.BluetoothAdapter.java
+    // Default: 0 when not used
     optional int32 bt_profile = 3;
+    // An identifier that can be used to match events for this device.
+    // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+    // Salt: Randomly generated 256 bit value
+    // Hash algorithm: HMAC-SHA256
+    // Size: 32 byte
+    // Default: null or empty if the device identifier is not known
+    optional bytes obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
 }
 
 /**
+ * Logs when a Bluetooth device connects and disconnects over ACL
+ *
+ * Logged from:
+ *    packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
+ *
+ * Next Tag: 3
+ */
+message BluetoothAclConnectionStateChanged {
+    // An identifier that can be used to match events for this device.
+    // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+    // Salt: Randomly generated 256 bit value
+    // Hash algorithm: HMAC-SHA256
+    // Size: 32 byte
+    // Default: null or empty if the device identifier is not known
+    optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+    // The state of the connection.
+    // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED.
+    optional android.bluetooth.ConnectionStateEnum state = 2;
+}
+
+/**
+ * Logs when a Bluetooth device connects and disconnects over SCO
+ *
+ * Logged from:
+ *    packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+ *    packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetClientStateMachine.java
+ *
+ * Next Tag: 4
+ */
+message BluetoothScoConnectionStateChanged {
+    // An identifier that can be used to match events for this device.
+    // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+    // Salt: Randomly generated 256 bit value
+    // Hash algorithm: HMAC-SHA256
+    // Size: 32 byte
+    // Default: null or empty if the device identifier is not known
+    optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+    // The state of the connection.
+    // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED.
+    optional android.bluetooth.ConnectionStateEnum state = 2;
+    // Codec used for this SCO connection
+    // Default: UNKNOWN
+    optional android.bluetooth.hfp.ScoCodec codec = 3;
+}
+
+// Logs when there is an event affecting Bluetooth device's link layer connection.
+// - This event is triggered when there is a related HCI command or event
+// - Users of this metrics can deduce Bluetooth device's connection state from these events
+// - HCI commands are logged before the command is sent, after receiving command status, and after
+//   receiving command complete
+// - HCI events are logged when they arrive
+//
+// Low level log from system/bt
+//
+// Bluetooth classic commands:
+// - CMD_CREATE_CONNECTION
+// - CMD_DISCONNECT
+// - CMD_CREATE_CONNECTION_CANCEL
+// - CMD_ACCEPT_CONNECTION_REQUEST
+// - CMD_REJECT_CONNECTION_REQUEST
+// - CMD_SETUP_ESCO_CONNECTION
+// - CMD_ACCEPT_ESCO_CONNECTION
+// - CMD_REJECT_ESCO_CONNECTION
+// - CMD_ENH_SETUP_ESCO_CONNECTION
+// - CMD_ENH_ACCEPT_ESCO_CONNECTION
+//
+// Bluetooth low energy commands:
+// - CMD_BLE_CREATE_LL_CONN [Only logged on error or when initiator filter policy is 0x00]
+// - CMD_BLE_CREATE_CONN_CANCEL [Only logged when there is an error]
+// - CMD_BLE_EXTENDED_CREATE_CONNECTION [Only logged on error or when initiator filter policy is 0x00]
+// - CMD_BLE_CLEAR_WHITE_LIST
+// - CMD_BLE_ADD_WHITE_LIST
+// - CMD_BLE_REMOVE_WHITE_LIST
+//
+// Bluetooth classic events:
+// - EVT_CONNECTION_COMP
+// - EVT_CONNECTION_REQUEST
+// - EVT_DISCONNECTION_COMP
+// - EVT_ESCO_CONNECTION_COMP
+// - EVT_ESCO_CONNECTION_CHANGED
+//
+// Bluetooth low energy meta events:
+// - BLE_EVT_CONN_COMPLETE_EVT
+// - BLE_EVT_ENHANCED_CONN_COMPLETE_EVT
+//
+// Next tag: 10
+message BluetoothLinkLayerConnectionEvent {
+    // An identifier that can be used to match events for this device.
+    // Currently, this is a salted hash of the MAC address of this Bluetooth device.
+    // Salt: Randomly generated 256 bit value
+    // Hash algorithm: HMAC-SHA256
+    // Size: 32 byte
+    // Default: null or empty if the device identifier is not known
+    optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES];
+    // Connection handle of this connection if available
+    // Range: 0x0000 - 0x0EFF (12 bits)
+    // Default: 0xFFFF if the handle is unknown
+    optional int32 connection_handle = 2;
+    // Direction of the link
+    // Default: DIRECTION_UNKNOWN
+    optional android.bluetooth.DirectionEnum direction = 3;
+    // Type of this link
+    // Default: LINK_TYPE_UNKNOWN
+    optional android.bluetooth.LinkTypeEnum type = 4;
+
+    // Reason metadata for this link layer connection event, rules for interpretation:
+    // 1. If hci_cmd is set and valid, hci_event can be either EVT_COMMAND_STATUS or
+    //    EVT_COMMAND_COMPLETE, ignore hci_ble_event in this case
+    // 2. If hci_event is set to EVT_BLE_META, look at hci_ble_event; otherwise, if hci_event is
+    //    set and valid, ignore hci_ble_event
+
+    // HCI command associated with this event
+    // Default: CMD_UNKNOWN
+    optional android.bluetooth.hci.CommandEnum hci_cmd = 5;
+    // HCI event associated with this event
+    // Default: EVT_UNKNOWN
+    optional android.bluetooth.hci.EventEnum hci_event = 6;
+    // HCI BLE meta event associated with this event
+    // Default: BLE_EVT_UNKNOWN
+    optional android.bluetooth.hci.BleMetaEventEnum hci_ble_event = 7;
+    // HCI command status code if this is triggerred by hci_cmd
+    // Default: STATUS_UNKNOWN
+    optional android.bluetooth.hci.StatusEnum cmd_status = 8;
+    // HCI reason code associated with this event
+    // Default: STATUS_UNKNOWN
+    optional android.bluetooth.hci.StatusEnum reason_code = 9;
+}
+
+
+/**
  * Logs when something is plugged into or removed from the USB-C connector.
  *
  * Logged from:
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 4d3c5d1..02eff0b6 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1108,18 +1108,6 @@
 Landroid/os/UserManager;->mService:Landroid/os/IUserManager;
 Landroid/os/UserManager;->removeUser(I)Z
 Landroid/os/Vibrator;-><init>()V
-Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String;
-Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String;
-Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long;
-Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map;
-Landroid/os/VintfObject;->report()[Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String;
 Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V
 Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
 Landroid/os/WorkSource;->mNum:I
@@ -1492,7 +1480,6 @@
 Landroid/test/AndroidTestCase;->getTestContext()Landroid/content/Context;
 Landroid/test/AndroidTestCase;->setTestContext(Landroid/content/Context;)V
 Landroid/test/InstrumentationTestCase;->runMethod(Ljava/lang/reflect/Method;I)V
-Landroid/test/RepetitiveTest;->numIterations()I
 Landroid/util/Singleton;-><init>()V
 Landroid/util/XmlPullAttributes;-><init>(Lorg/xmlpull/v1/XmlPullParser;)V
 Landroid/util/XmlPullAttributes;->mParser:Lorg/xmlpull/v1/XmlPullParser;
@@ -1825,22 +1812,10 @@
 Lcom/android/internal/os/RuntimeInit;->initialized:Z
 Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V
 Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder;
-Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V
-Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I
-Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V
 Lcom/android/internal/os/ZygoteConnection;->closeSocket()V
-Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor;
-Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I
 Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket;
 Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream;
 Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials;
-Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String;
 Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
 Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources;
 Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 98c5a0fb..836627e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.os.Process.myUid;
 
 import static java.lang.Character.MIN_VALUE;
 
@@ -123,6 +124,7 @@
 import android.view.autofill.IAutofillWindowPresenter;
 import android.view.contentcapture.ContentCaptureContext;
 import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureSession;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -1025,7 +1027,7 @@
      */
     @Nullable private ContentCaptureManager getContentCaptureManager() {
         // ContextCapture disabled for system apps
-        if (getApplicationInfo().isSystemApp()) return null;
+        if (!UserHandle.isApp(myUid())) return null;
         if (mContentCaptureManager == null) {
             mContentCaptureManager = getSystemService(ContentCaptureManager.class);
         }
@@ -1033,13 +1035,15 @@
     }
 
     /** @hide */ private static final int CONTENT_CAPTURE_START = 1;
-    /** @hide */ private static final int CONTENT_CAPTURE_FLUSH = 2;
-    /** @hide */ private static final int CONTENT_CAPTURE_STOP = 3;
+    /** @hide */ private static final int CONTENT_CAPTURE_PAUSE = 2;
+    /** @hide */ private static final int CONTENT_CAPTURE_RESUME = 3;
+    /** @hide */ private static final int CONTENT_CAPTURE_STOP = 4;
 
     /** @hide */
     @IntDef(prefix = { "CONTENT_CAPTURE_" }, value = {
             CONTENT_CAPTURE_START,
-            CONTENT_CAPTURE_FLUSH,
+            CONTENT_CAPTURE_PAUSE,
+            CONTENT_CAPTURE_RESUME,
             CONTENT_CAPTURE_STOP
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -1048,9 +1052,8 @@
 
     private void notifyContentCaptureManagerIfNeeded(@ContentCaptureNotificationType int type) {
         final ContentCaptureManager cm = getContentCaptureManager();
-        if (cm == null) {
-            return;
-        }
+        if (cm == null) return;
+
         switch (type) {
             case CONTENT_CAPTURE_START:
                 //TODO(b/111276913): decide whether the InteractionSessionId should be
@@ -1062,8 +1065,11 @@
                 }
                 cm.onActivityStarted(mToken, getComponentName(), flags);
                 break;
-            case CONTENT_CAPTURE_FLUSH:
-                cm.flush();
+            case CONTENT_CAPTURE_PAUSE:
+                cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_PAUSED);
+                break;
+            case CONTENT_CAPTURE_RESUME:
+                cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_RESUMED);
                 break;
             case CONTENT_CAPTURE_STOP:
                 cm.onActivityStopped();
@@ -1755,7 +1761,7 @@
             }
         }
         mCalled = true;
-        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH);
+        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_RESUME);
     }
 
     /**
@@ -2149,7 +2155,7 @@
             }
         }
         mCalled = true;
-        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH);
+        notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE);
     }
 
     /**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d423260..e0b8d78 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3705,11 +3705,16 @@
      * Returns whether switching to provided user was successful.
      *
      * @param user the user to switch to.
+     *
+     * @throws IllegalArgumentException if the user is null.
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
-    public boolean switchUser(UserHandle user) {
+    public boolean switchUser(@NonNull UserHandle user) {
+        if (user == null) {
+            throw new IllegalArgumentException("UserHandle cannot be null.");
+        }
         return switchUser(user.getIdentifier());
     }
 
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 1f01e26..5cac048 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -320,4 +320,10 @@
 
     /** Remove pending backup for the given userId. */
     public abstract void clearPendingBackup(int userId);
+
+    /**
+     * When power button is very long pressed, call this interface to do some pre-shutdown work
+     * like persisting database etc.
+     */
+    public abstract void prepareForPossibleShutdown();
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9247486..6d7c547 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2168,6 +2168,74 @@
     public @interface SetPrivateDnsModeResultConstants {}
 
     /**
+     * Activity action: Starts the administrator to get the mode for the provisioning.
+     * This intent may contain the following extras:
+     * <ul>
+     *     <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}</li>
+     *     <li>{@link #EXTRA_PROVISIONING_IMEI}</li>
+     *     <li>{@link #EXTRA_PROVISIONING_SERIAL_NUMBER}</li>
+     * </ul>
+     *
+     * <p>The target activity should return one of the following values in
+     * {@link #EXTRA_PROVISIONING_MODE} as result:
+     * <ul>
+     *     <li>{@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}</li>
+     *     <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE}</li>
+     *     <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE}</li>
+     * </ul>
+     *
+     * <p>The target activity may also return the account that needs to be migrated from primary
+     * user to managed profile in case of a profile owner provisioning in
+     * {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE} as result.
+     */
+    public static final String ACTION_GET_PROVISIONING_MODE =
+            "android.app.action.GET_PROVISIONING_MODE";
+
+    /**
+     * A string extra holding the IMEI (International Mobile Equipment Identity) of the device.
+     */
+    public static final String EXTRA_PROVISIONING_IMEI = "android.app.extra.PROVISIONING_IMEI";
+
+    /**
+     * A string extra holding the serial number of the device.
+     */
+    public static final String EXTRA_PROVISIONING_SERIAL_NUMBER =
+            "android.app.extra.PROVISIONING_SERIAL_NUMBER";
+
+    /**
+     * An intent extra holding the provisioning mode returned by the administrator.
+     * The value for this extra should be one of the following:
+     * <ul>
+     *     <li>{@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}</li>
+     *     <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE}</li>
+     *     <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE}</li>
+     * </ul>
+     */
+    public static final String EXTRA_PROVISIONING_MODE =
+            "android.app.extra.PROVISIONING_MODE";
+
+    /**
+     * The provisioning mode for fully managed device.
+     */
+    public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE = 1;
+
+    /**
+     * The provisioning mode for managed profile.
+     */
+    public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2;
+
+    /**
+     * The provisioning mode for managed profile on a fully managed device.
+     */
+    public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 3;
+
+    /**
+     * Activity action: Starts the administrator to show policy compliance for the provisioning.
+     */
+    public static final String ACTION_ADMIN_POLICY_COMPLIANCE =
+            "android.app.action.ADMIN_POLICY_COMPLIANCE";
+
+    /**
      * Return true if the given administrator component is currently active (enabled) in the system.
      *
      * @param admin The administrator component to check for.
diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java
index a79ad2f..aaae57e5 100644
--- a/core/java/android/app/usage/EventList.java
+++ b/core/java/android/app/usage/EventList.java
@@ -103,21 +103,4 @@
         }
         return result;
     }
-
-    /**
-     * Remove events of certain type on or after a timestamp.
-     * @param type The type of event to remove.
-     * @param timeStamp the timeStamp on or after which to remove the event.
-     */
-    public void removeOnOrAfter(int type, long timeStamp) {
-        for (int i = mEvents.size() - 1; i >= 0; i--) {
-            UsageEvents.Event event = mEvents.get(i);
-            if (event.mTimeStamp < timeStamp) {
-                break;
-            }
-            if (event.mEventType == type) {
-                mEvents.remove(i);
-            }
-        }
-    }
 }
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index d7a5328..2c5fe04 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -245,10 +245,18 @@
         public static final int FLUSH_TO_DISK = 25;
 
         /**
+         * An event type denoting that the device underwent a shutdown process.
+         * A DEVICE_SHUTDOWN event should be treated as if all started activities and foreground
+         * services are now stopped and no explicit {@link #ACTIVITY_STOPPED} and
+         * {@link #FOREGROUND_SERVICE_STOP} events will be generated for them.
+         */
+        public static final int DEVICE_SHUTDOWN = 26;
+
+        /**
          * Keep in sync with the greatest event type value.
          * @hide
          */
-        public static final int MAX_EVENT_TYPE = 25;
+        public static final int MAX_EVENT_TYPE = 26;
 
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 308180b..94a2a3e 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -21,6 +21,7 @@
 import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
 import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
 import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageEvents.Event.END_OF_DAY;
 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
@@ -119,12 +120,9 @@
     public int mLastEvent;
 
     /**
-     * If an activity is visible(onStart(), onPause() states) or in foreground (onResume() state),
-     * it has one entry in this map. When an activity becomes invisible (onStop() or onDestroy()),
-     * it is removed from this map.
      * Key is instanceId of the activity (ActivityRecode appToken hashCode)..
-     * Value is this activity's last event, one of ACTIVITY_RESUMED or
-     * ACTIVITY_PAUSED.
+     * Value is this activity's last event, one of ACTIVITY_RESUMED, ACTIVITY_PAUSED or
+     * ACTIVITY_STOPPED.
      * {@hide}
      */
     public SparseIntArray mActivities = new SparseIntArray();
@@ -560,6 +558,7 @@
                 mLastTimeForegroundServiceUsed = timeStamp;
                 mForegroundServices.put(className, eventType);
                 break;
+            case DEVICE_SHUTDOWN:
             case FLUSH_TO_DISK:
                 // update usage of all active activities/services.
                 if (hasForegroundActivity()) {
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 2edad35..cc3ab00 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -98,6 +98,12 @@
     public abstract void prepareShutdown();
 
     /**
+     * When the device power button is long pressed for 3.5 seconds, prepareForPossibleShutdown()
+     * is called.
+     */
+    public abstract void prepareForPossibleShutdown();
+
+    /**
      * Returns true if the app has not been used for a certain amount of time. How much time?
      * Could be hours, could be days, who knows?
      *
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 83563d0..359adbd 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -55,6 +55,7 @@
     public static final int PACKAGE_PERMISSION_CONTROLLER = 6;
     public static final int PACKAGE_WELLBEING = 7;
     public static final int PACKAGE_DOCUMENTER = 8;
+    public static final int PACKAGE_CONFIGURATOR = 9;
     @IntDef(value = {
         PACKAGE_SYSTEM,
         PACKAGE_SETUP_WIZARD,
@@ -65,6 +66,7 @@
         PACKAGE_PERMISSION_CONTROLLER,
         PACKAGE_WELLBEING,
         PACKAGE_DOCUMENTER,
+        PACKAGE_CONFIGURATOR,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface KnownPackage {}
@@ -137,6 +139,12 @@
     public abstract void setLocationPackagesProvider(PackagesProvider provider);
 
     /**
+     * Set the location extra packages provider.
+     * @param provider The packages provider.
+     */
+    public abstract  void setLocationExtraPackagesProvider(PackagesProvider provider);
+
+    /**
      * Sets the voice interaction packages provider.
      * @param provider The packages provider.
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1ac0ab6..dbf3574 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3777,9 +3777,11 @@
             ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
         }
 
+        final boolean extractNativeLibsDefault =
+                owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q;
         if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
-                true)) {
+                extractNativeLibsDefault)) {
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index a3395ac..5d2cf0a 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -203,6 +203,16 @@
     @TestApi
     public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000;
 
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding to the
+     * {@code configurator} value of {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000;
+
 
     /** @hide */
     @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
@@ -222,6 +232,7 @@
             PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER,
             PROTECTION_FLAG_WELLBEING,
             PROTECTION_FLAG_DOCUMENTER,
+            PROTECTION_FLAG_CONFIGURATOR,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionFlags {}
@@ -417,6 +428,9 @@
         if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) {
             protLevel += "|documenter";
         }
+        if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) {
+            protLevel += "|configurator";
+        }
         return protLevel;
     }
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c4b315e..dcd6e2e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -98,6 +98,12 @@
  * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p>
  */
 public class Resources {
+    /**
+     * The {@code null} resource ID. This denotes an invalid resource ID that is returned by the
+     * system when a resource is not found or the value is set to {@code @null} in XML.
+     */
+    public static final @AnyRes int ID_NULL = 0;
+
     static final String TAG = "Resources";
 
     private static final Object sSync = new Object();
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 508626b..d53834c 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -19,6 +19,7 @@
 import android.annotation.AnyRes;
 import android.annotation.ColorInt;
 import android.annotation.Nullable;
+import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
 import android.annotation.UnsupportedAppUsage;
 import android.content.pm.ActivityInfo;
@@ -63,13 +64,15 @@
     }
 
     // STYLE_ prefixed constants are offsets within the typed data array.
-    static final int STYLE_NUM_ENTRIES = 6;
+    // Keep this in sync with libs/androidfw/include/androidfw/AttributeResolution.h
+    static final int STYLE_NUM_ENTRIES = 7;
     static final int STYLE_TYPE = 0;
     static final int STYLE_DATA = 1;
     static final int STYLE_ASSET_COOKIE = 2;
     static final int STYLE_RESOURCE_ID = 3;
     static final int STYLE_CHANGING_CONFIGURATIONS = 4;
     static final int STYLE_DENSITY = 5;
+    static final int SYTLE_SOURCE_STYLE_RESOURCE_ID = 6;
 
     @UnsupportedAppUsage
     private final Resources mResources;
@@ -1098,6 +1101,31 @@
     }
 
     /**
+     * Returns the resource ID of the style against which the specified attribute was resolved,
+     * otherwise returns defValue.
+     *
+     * @param index Index of attribute whose source style to retrieve.
+     * @param defValue Value to return if the attribute is not defined or
+     *                 not a resource.
+     *
+     * @return Attribute source style resource ID or defValue if it was not resolved in any style.
+     * @throws RuntimeException if the TypedArray has already been recycled.
+     */
+    @StyleRes
+    public int getSourceStyleResourceId(@StyleableRes int index, @StyleRes int defValue) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
+        index *= STYLE_NUM_ENTRIES;
+        final int resid = mData[index + SYTLE_SOURCE_STYLE_RESOURCE_ID];
+        if (resid != 0) {
+            return resid;
+        }
+        return defValue;
+    }
+
+    /**
      * Determines whether there is an attribute at <var>index</var>.
      * <p>
      * <strong>Note:</strong> If the attribute was set to {@code @empty} or
@@ -1309,6 +1337,7 @@
                 data[index + STYLE_CHANGING_CONFIGURATIONS]);
         outValue.density = data[index + STYLE_DENSITY];
         outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
+        outValue.sourceStyleResourceId = data[index + SYTLE_SOURCE_STYLE_RESOURCE_ID];
         return true;
     }
 
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index eb3414d2..8aac1bf 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -42,13 +42,13 @@
     /**
      * The hardware is unavailable. Try again later.
      */
-    public static final int BIOMETRIC_ERROR_UNAVAILABLE =
+    public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE =
             BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
 
     /**
      * The user does not have any biometrics enrolled.
      */
-    public static final int BIOMETRIC_ERROR_NO_BIOMETRICS =
+    public static final int BIOMETRIC_ERROR_NONE_ENROLLED =
             BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
 
     /**
@@ -58,8 +58,8 @@
             BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
 
     @IntDef({BIOMETRIC_SUCCESS,
-            BIOMETRIC_ERROR_UNAVAILABLE,
-            BIOMETRIC_ERROR_NO_BIOMETRICS,
+            BIOMETRIC_ERROR_HW_UNAVAILABLE,
+            BIOMETRIC_ERROR_NONE_ENROLLED,
             BIOMETRIC_ERROR_NO_HARDWARE})
     @interface BiometricError {}
 
@@ -95,8 +95,8 @@
      * Determine if biometrics can be used. In other words, determine if {@link BiometricPrompt}
      * can be expected to be shown (hardware available, templates enrolled, user-enabled).
      *
-     * @return Returns {@link #BIOMETRIC_ERROR_NO_BIOMETRICS} if the user does not have any
-     *     enrolled, or {@link #BIOMETRIC_ERROR_UNAVAILABLE} if none are currently
+     * @return Returns {@link #BIOMETRIC_ERROR_NONE_ENROLLED} if the user does not have any
+     *     enrolled, or {@link #BIOMETRIC_ERROR_HW_UNAVAILABLE} if none are currently
      *     supported/enabled. Returns {@link #BIOMETRIC_SUCCESS} if a biometric can currently be
      *     used (enrolled and available).
      */
@@ -113,7 +113,7 @@
                 return BIOMETRIC_ERROR_NO_HARDWARE;
             } else {
                 Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
-                return BIOMETRIC_ERROR_UNAVAILABLE;
+                return BIOMETRIC_ERROR_HW_UNAVAILABLE;
             }
         }
     }
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index f652f85..c69b68e4 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -235,7 +235,6 @@
          * requiring confirmation.
          *
          * @param requireConfirmation
-         * @hide
          */
         public Builder setRequireConfirmation(boolean requireConfirmation) {
             mBundle.putBoolean(KEY_REQUIRE_CONFIRMATION, requireConfirmation);
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index be054297..8c74ddc 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -91,9 +91,7 @@
      *
      * @return The matching brightness correction, or null.
      *
-     * @hide
      */
-    @SystemApi
     @Nullable
     public BrightnessCorrection getCorrectionByPackageName(String packageName) {
         return mCorrectionsByPackageName.get(packageName);
@@ -106,10 +104,7 @@
      *      The app category.
      *
      * @return The matching brightness correction, or null.
-     *
-     * @hide
      */
-    @SystemApi
     @Nullable
     public BrightnessCorrection getCorrectionByCategory(int category) {
         return mCorrectionsByCategory.get(category);
@@ -416,9 +411,7 @@
          *
          * @return The maximum number of corrections by package name allowed.
          *
-         * @hide
          */
-        @SystemApi
         public int getMaxCorrectionsByPackageName() {
             return MAX_CORRECTIONS_BY_PACKAGE_NAME;
         }
@@ -428,9 +421,7 @@
          *
          * @return The maximum number of corrections by category allowed.
          *
-         * @hide
          */
-        @SystemApi
         public int getMaxCorrectionsByCategory() {
             return MAX_CORRECTIONS_BY_CATEGORY;
         }
@@ -451,9 +442,7 @@
          *      Maximum number of corrections by package name exceeded (see
          *      {@link #getMaxCorrectionsByPackageName}).
          *
-         * @hide
          */
-        @SystemApi
         public Builder addCorrectionByPackageName(String packageName,
                 BrightnessCorrection correction) {
             if (mCorrectionsByPackageName.size() >= getMaxCorrectionsByPackageName()) {
@@ -479,9 +468,7 @@
          *      Maximum number of corrections by category exceeded (see
          *      {@link #getMaxCorrectionsByCategory}).
          *
-         * @hide
          */
-        @SystemApi
         public Builder addCorrectionByCategory(@ApplicationInfo.Category int category,
                 BrightnessCorrection correction) {
             if (mCorrectionsByCategory.size() >= getMaxCorrectionsByCategory()) {
@@ -504,8 +491,6 @@
 
         /**
          * Builds the {@link BrightnessConfiguration}.
-         *
-         * A brightness curve <b>must</b> be set before calling this.
          */
         public BrightnessConfiguration build() {
             if (mCurveLux == null || mCurveNits == null) {
diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java
index c4e0e3b..6a073ff 100644
--- a/core/java/android/hardware/display/BrightnessCorrection.java
+++ b/core/java/android/hardware/display/BrightnessCorrection.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.MathUtils;
@@ -41,6 +42,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class BrightnessCorrection implements Parcelable {
 
     private static final int SCALE_AND_TRANSLATE_LOG = 1;
@@ -98,6 +100,24 @@
         return mImplementation.toString();
     }
 
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof BrightnessCorrection)) {
+            return false;
+        }
+        BrightnessCorrection other = (BrightnessCorrection) o;
+        return other.mImplementation.equals(mImplementation);
+    }
+
+    @Override
+    public int hashCode() {
+        return mImplementation.hashCode();
+    }
+
     public static final Creator<BrightnessCorrection> CREATOR =
             new Creator<BrightnessCorrection>() {
                 public BrightnessCorrection createFromParcel(Parcel in) {
@@ -215,6 +235,26 @@
         }
 
         @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+            if (!(o instanceof ScaleAndTranslateLog)) {
+                return false;
+            }
+            ScaleAndTranslateLog other = (ScaleAndTranslateLog) o;
+            return other.mScale == mScale && other.mTranslate == mTranslate;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 1;
+            result = result * 31 + Float.hashCode(mScale);
+            result = result * 31 + Float.hashCode(mTranslate);
+            return result;
+        }
+
+        @Override
         public void writeToParcel(Parcel dest) {
             dest.writeInt(SCALE_AND_TRANSLATE_LOG);
             dest.writeFloat(mScale);
diff --git a/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
index d382eb9..bdd5ab6 100644
--- a/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
+++ b/core/java/android/hardware/hdmi/HdmiAudioSystemClient.java
@@ -15,10 +15,12 @@
  */
 package android.hardware.hdmi;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
@@ -56,6 +58,21 @@
         mHandler = handler == null ? new Handler(Looper.getMainLooper()) : handler;
     }
 
+    /**
+     * Callback interface used to get the set System Audio Mode result.
+     *
+     * @hide
+     */
+    // TODO(b/110094868): unhide and add @SystemApi for Q
+    public interface SetSystemAudioModeCallback {
+        /**
+         * Called when the input was changed.
+         *
+         * @param result the result of the set System Audio Mode
+         */
+        void onComplete(int result);
+    }
+
     /** @hide */
     // TODO(b/110094868): unhide and add @SystemApi for Q
     @Override
@@ -117,4 +134,34 @@
             mPendingReportAudioStatus = true;
         }
     }
+
+    /**
+     * Set System Audio Mode on/off with audio system device.
+     *
+     * @param state true to set System Audio Mode on. False to set off.
+     * @param callback callback offer the setting result.
+     *
+     * @hide
+     */
+    // TODO(b/110094868): unhide and add @SystemApi for Q
+    public void setSystemAudioMode(boolean state, @NonNull SetSystemAudioModeCallback callback) {
+        // TODO(amyjojo): implement this when needed.
+    }
+
+    /**
+     * When device is switching to an audio only source, this method is called to broadcast
+     * a setSystemAudioMode on message to the HDMI CEC system without querying Active Source or
+     * TV supporting System Audio Control or not. This is to get volume control passthrough
+     * from STB even if TV does not support it.
+     *
+     * @hide
+     */
+    // TODO(b/110094868): unhide and add @SystemApi for Q
+    public void setSystemAudioModeOnForAudioOnlySource() {
+        try {
+            mService.setSystemAudioModeOnForAudioOnlySource();
+        } catch (RemoteException e) {
+            Log.d(TAG, "Failed to set System Audio Mode on for Audio Only source");
+        }
+    }
 }
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index f5d288e..a98b31a 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -33,6 +33,8 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import java.util.List;
+
 /**
  * The {@link HdmiControlManager} class is used to send HDMI control messages
  * to attached CEC devices.
@@ -53,6 +55,10 @@
 
     @Nullable private final IHdmiControlService mService;
 
+    private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
+
+    private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+
     /**
      * Broadcast Action: Display OSD message.
      * <p>Send when the service has a message to display on screen for events
@@ -404,6 +410,72 @@
     }
 
     /**
+     * Get a snapshot of the real-time status of the remote devices.
+     *
+     * @return a list of {@link HdmiDeviceInfo} of the devices connected to the current device.
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public List<HdmiDeviceInfo> getConnectedDevicesList() {
+        try {
+            return mService.getDeviceList();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Power off the target device.
+     *
+     * @param deviceInfo HdmiDeviceInfo of the device to be powered off
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public void powerOffRemoteDevice(HdmiDeviceInfo deviceInfo) {
+        try {
+            mService.powerOffRemoteDevice(
+                    deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Power on the target device.
+     *
+     * @param deviceInfo HdmiDeviceInfo of the device to be powered on
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) {
+        try {
+            mService.powerOnRemoteDevice(
+                    deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Ask the target device to be the new Active Source.
+     *
+     * @param deviceInfo HdmiDeviceInfo of the target device
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public void askRemoteDeviceToBecomeActiveSource(HdmiDeviceInfo deviceInfo) {
+        try {
+            mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Controls standby mode of the system. It will also try to turn on/off the connected devices if
      * necessary.
      *
@@ -432,6 +504,46 @@
     }
 
     /**
+     * Get the physical address of the device.
+     *
+     * @hide
+     */
+    public int getPhysicalAddress() {
+        if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
+            return mPhysicalAddress;
+        }
+        try {
+            mPhysicalAddress = mService.getPhysicalAddress();
+            return mPhysicalAddress;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Check if the target device is connected to the current device. The
+     * API also returns true if the current device is the target.
+     *
+     * @param targetDevice {@link HdmiDeviceInfo} of the target device.
+     * @return true if {@code device} is directly or indirectly connected to the
+     *
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public boolean isTargetDeviceConnected(HdmiDeviceInfo targetDevice) {
+        mPhysicalAddress = getPhysicalAddress();
+        if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
+            return false;
+        }
+        int targetPhysicalAddress = targetDevice.getPhysicalAddress();
+        if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
+            return false;
+        }
+        return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, mPhysicalAddress)
+            != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE;
+    }
+
+    /**
      * Listener used to get hotplug event from HDMI port.
      */
     public interface HotplugEventListener {
diff --git a/core/java/android/hardware/hdmi/HdmiUtils.java b/core/java/android/hardware/hdmi/HdmiUtils.java
new file mode 100644
index 0000000..3081738
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiUtils.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+package android.hardware.hdmi;
+
+/**
+ * Various utilities to handle HDMI CEC messages.
+ *
+ * TODO(b/110094868): unhide for Q
+ * @hide
+ */
+public class HdmiUtils {
+
+    /**
+     * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
+     */
+    static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
+    static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;
+
+    private HdmiUtils() { /* cannot be instantiated */ }
+
+    /**
+     * Method to parse target physical address to the port number on the current device.
+     *
+     * <p>This check assumes target address is valid.
+     *
+     * @param targetPhysicalAddress is the physical address of the target device
+     * @param myPhysicalAddress is the physical address of the current device
+     * @return
+     * If the target device is under the current device, return the port number of current device
+     * that the target device is connected to. This also applies to the devices that are indirectly
+     * connected to the current device.
+     *
+     * <p>If the target device has the same physical address as the current device, return
+     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
+     *
+     * <p>If the target device is not under the current device, return
+     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
+     */
+    public static int getLocalPortFromPhysicalAddress(
+            int targetPhysicalAddress, int myPhysicalAddress) {
+        if (myPhysicalAddress == targetPhysicalAddress) {
+            return TARGET_SAME_PHYSICAL_ADDRESS;
+        }
+
+        int mask = 0xF000;
+        int finalMask = 0xF000;
+        int maskedAddress = myPhysicalAddress;
+
+        while (maskedAddress != 0) {
+            maskedAddress = myPhysicalAddress & mask;
+            finalMask |= mask;
+            mask >>= 4;
+        }
+
+        int portAddress = targetPhysicalAddress & finalMask;
+        if ((portAddress & (finalMask << 4)) != myPhysicalAddress) {
+            return TARGET_NOT_UNDER_LOCAL_DEVICE;
+        }
+
+        mask <<= 4;
+        int port = portAddress & mask;
+        while ((port >> 4) != 0) {
+            port >>= 4;
+        }
+        return port;
+    }
+}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 2b8d00b..1cd9920 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -50,6 +50,7 @@
     List<HdmiPortInfo> getPortInfo();
     boolean canChangeSystemAudioMode();
     boolean getSystemAudioMode();
+    int getPhysicalAddress();
     void setSystemAudioMode(boolean enabled, IHdmiControlCallback callback);
     void addSystemAudioModeChangeListener(IHdmiSystemAudioModeChangeListener listener);
     void removeSystemAudioModeChangeListener(IHdmiSystemAudioModeChangeListener listener);
@@ -60,6 +61,9 @@
     void setInputChangeListener(IHdmiInputChangeListener listener);
     List<HdmiDeviceInfo> getInputDevices();
     List<HdmiDeviceInfo> getDeviceList();
+    void powerOffRemoteDevice(int logicalAddress, int powerStatus);
+    void powerOnRemoteDevice(int logicalAddress, int powerStatus);
+    void askRemoteDeviceToBecomeActiveSource(int physicalAddress);
     void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
             boolean hasVendorId);
     void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
@@ -73,4 +77,5 @@
     void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
     void setStandbyMode(boolean isStandbyModeOn);
     void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
+    void setSystemAudioModeOnForAudioOnlySource();
 }
diff --git a/core/java/android/net/IpPrefixParcelable.aidl b/core/java/android/net/IpPrefixParcelable.aidl
new file mode 100644
index 0000000..93a8d41
--- /dev/null
+++ b/core/java/android/net/IpPrefixParcelable.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.net;
+
+parcelable IpPrefixParcelable {
+    String address;
+    int prefixLength;
+}
\ No newline at end of file
diff --git a/core/java/android/net/LinkAddressParcelable.aidl b/core/java/android/net/LinkAddressParcelable.aidl
new file mode 100644
index 0000000..af8e79b
--- /dev/null
+++ b/core/java/android/net/LinkAddressParcelable.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.net;
+
+parcelable LinkAddressParcelable {
+    String address;
+    int prefixLength;
+    int flags;
+    int scope;
+}
\ No newline at end of file
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 617125b3..c2963fd 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -191,6 +191,7 @@
             }
             setMtu(source.mMtu);
             mTcpBufferSizes = source.mTcpBufferSizes;
+            mNat64Prefix = source.mNat64Prefix;
         }
     }
 
diff --git a/core/java/android/net/LinkPropertiesParcelable.aidl b/core/java/android/net/LinkPropertiesParcelable.aidl
new file mode 100644
index 0000000..b153dc7
--- /dev/null
+++ b/core/java/android/net/LinkPropertiesParcelable.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.net;
+
+import android.net.IpPrefixParcelable;
+import android.net.LinkAddressParcelable;
+import android.net.ProxyInfoParcelable;
+import android.net.RouteInfoParcelable;
+
+parcelable LinkPropertiesParcelable {
+    String ifaceName;
+    LinkAddressParcelable[] linkAddresses;
+    String[] dnses;
+    String[] pcscfs;
+    String[] validatedPrivateDnses;
+    boolean usePrivateDns;
+    String privateDnsServerName;
+    String domains;
+    RouteInfoParcelable[] routes;
+    ProxyInfoParcelable httpProxy;
+    int mtu;
+    String tcpBufferSizes;
+    IpPrefixParcelable nat64Prefix;
+    LinkPropertiesParcelable[] stackedLinks;
+}
\ No newline at end of file
diff --git a/core/java/android/net/ProxyInfoParcelable.aidl b/core/java/android/net/ProxyInfoParcelable.aidl
new file mode 100644
index 0000000..59fd846
--- /dev/null
+++ b/core/java/android/net/ProxyInfoParcelable.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.net;
+
+parcelable ProxyInfoParcelable {
+    String host;
+    int port;
+    String[] exclusionList;
+    String pacFileUrl;
+}
diff --git a/core/java/android/net/RouteInfoParcelable.aidl b/core/java/android/net/RouteInfoParcelable.aidl
new file mode 100644
index 0000000..15bcdcf
--- /dev/null
+++ b/core/java/android/net/RouteInfoParcelable.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package android.net;
+
+import android.net.IpPrefixParcelable;
+
+parcelable RouteInfoParcelable {
+    IpPrefixParcelable destination;
+    String gatewayAddr;
+    String ifaceName;
+    int type;
+}
diff --git a/core/java/android/net/ipmemorystore/NetworkAttributes.java b/core/java/android/net/ipmemorystore/NetworkAttributes.java
index d7e5b27..b932d21 100644
--- a/core/java/android/net/ipmemorystore/NetworkAttributes.java
+++ b/core/java/android/net/ipmemorystore/NetworkAttributes.java
@@ -28,6 +28,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
+import java.util.StringJoiner;
 
 /**
  * A POD object to represent attributes of a single L2 network entry.
@@ -207,4 +208,52 @@
     public int hashCode() {
         return Objects.hash(assignedV4Address, groupHint, dnsAddresses, mtu);
     }
+
+    /** Pretty print */
+    @Override
+    public String toString() {
+        final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
+        final ArrayList<String> nullFields = new ArrayList<>();
+
+        if (null != assignedV4Address) {
+            resultJoiner.add("assignedV4Addr :");
+            resultJoiner.add(assignedV4Address.toString());
+        } else {
+            nullFields.add("assignedV4Addr");
+        }
+
+        if (null != groupHint) {
+            resultJoiner.add("groupHint :");
+            resultJoiner.add(groupHint);
+        } else {
+            nullFields.add("groupHint");
+        }
+
+        if (null != dnsAddresses) {
+            resultJoiner.add("dnsAddr : [");
+            for (final InetAddress addr : dnsAddresses) {
+                resultJoiner.add(addr.getHostAddress());
+            }
+            resultJoiner.add("]");
+        } else {
+            nullFields.add("dnsAddr");
+        }
+
+        if (null != mtu) {
+            resultJoiner.add("mtu :");
+            resultJoiner.add(mtu.toString());
+        } else {
+            nullFields.add("mtu");
+        }
+
+        if (!nullFields.isEmpty()) {
+            resultJoiner.add("; Null fields : [");
+            for (final String field : nullFields) {
+                resultJoiner.add(field);
+            }
+            resultJoiner.add("]");
+        }
+
+        return resultJoiner.toString();
+    }
 }
diff --git a/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java b/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java
index 0cb37e9..d040dcc 100644
--- a/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java
+++ b/core/java/android/net/ipmemorystore/SameL3NetworkResponse.java
@@ -128,4 +128,19 @@
     public int hashCode() {
         return Objects.hash(l2Key1, l2Key2, confidence);
     }
+
+    @Override
+    /** Pretty print */
+    public String toString() {
+        switch (getNetworkSameness()) {
+            case NETWORK_SAME:
+                return "\"" + l2Key1 + "\" same L3 network as \"" + l2Key2 + "\"";
+            case NETWORK_DIFFERENT:
+                return "\"" + l2Key1 + "\" different L3 network from \"" + l2Key2 + "\"";
+            case NETWORK_NEVER_CONNECTED:
+                return "\"" + l2Key1 + "\" can't be tested against \"" + l2Key2 + "\"";
+            default:
+                return "Buggy sameness value ? \"" + l2Key1 + "\", \"" + l2Key2 + "\"";
+        }
+    }
 }
diff --git a/core/java/android/net/ipmemorystore/Status.java b/core/java/android/net/ipmemorystore/Status.java
index 5b016ec..95e5042 100644
--- a/core/java/android/net/ipmemorystore/Status.java
+++ b/core/java/android/net/ipmemorystore/Status.java
@@ -26,6 +26,8 @@
 public class Status {
     public static final int SUCCESS = 0;
 
+    public static final int ERROR_DATABASE_CANNOT_BE_OPENED = -1;
+
     public final int resultCode;
 
     public Status(final int resultCode) {
@@ -47,4 +49,14 @@
     public boolean isSuccess() {
         return SUCCESS == resultCode;
     }
+
+    /** Pretty print */
+    @Override
+    public String toString() {
+        switch (resultCode) {
+            case SUCCESS: return "SUCCESS";
+            case ERROR_DATABASE_CANNOT_BE_OPENED: return "DATABASE CANNOT BE OPENED";
+            default: return "Unknown value ?!";
+        }
+    }
 }
diff --git a/core/java/android/net/ipmemorystore/Utils.java b/core/java/android/net/ipmemorystore/Utils.java
new file mode 100644
index 0000000..73d8c83
--- /dev/null
+++ b/core/java/android/net/ipmemorystore/Utils.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ipmemorystore;
+
+import android.annotation.NonNull;
+
+/** {@hide} */
+public class Utils {
+    /** Pretty print */
+    public static String blobToString(final Blob blob) {
+        final StringBuilder sb = new StringBuilder("Blob : [");
+        if (blob.data.length <= 24) {
+            appendByteArray(sb, blob.data, 0, blob.data.length);
+        } else {
+            appendByteArray(sb, blob.data, 0, 16);
+            sb.append("...");
+            appendByteArray(sb, blob.data, blob.data.length - 8, blob.data.length);
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+
+    // Adds the hex representation of the array between the specified indices (inclusive, exclusive)
+    private static void appendByteArray(@NonNull final StringBuilder sb, @NonNull final byte[] ar,
+            final int from, final int to) {
+        for (int i = from; i < to; ++i) {
+            sb.append(String.format("%02X", ar[i]));
+        }
+    }
+}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index b15a4d3..cbb3909 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -114,7 +114,6 @@
         }
     }
 
-    // TODO(b/111441001) Connect up with BugreportListener methods.
     private final class DumpstateListener extends IDumpstateListener.Stub
             implements DeathRecipient {
         private final BugreportListener mListener;
@@ -130,35 +129,35 @@
 
         @Override
         public void onProgress(int progress) throws RemoteException {
-            // TODO(b/111441001): implement
+            mListener.onProgress(progress);
         }
 
         @Override
         public void onError(int errorCode) throws RemoteException {
-            // TODO(b/111441001): implement
+            mListener.onError(errorCode);
         }
 
         @Override
         public void onFinished(long durationMs, String title, String description)
                 throws RemoteException {
-            // TODO(b/111441001): implement
+            mListener.onFinished(durationMs, title, description);
         }
 
         // Old methods; should go away
         @Override
         public void onProgressUpdated(int progress) throws RemoteException {
-            // TODO(b/111441001): implement
+            // TODO(b/111441001): remove from interface
         }
 
         @Override
         public void onMaxProgressUpdated(int maxProgress) throws RemoteException {
-            // TODO(b/111441001): implement
+            // TODO(b/111441001): remove from interface
         }
 
         @Override
         public void onSectionComplete(String title, int status, int size, int durationMs)
                 throws RemoteException {
-            // TODO(b/111441001): implement
+            // TODO(b/111441001): remove from interface
         }
     }
 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 9fea873..2d61a4e 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -289,6 +289,26 @@
                 "ro.build.version.preview_sdk", 0);
 
         /**
+         * The SDK fingerprint for a given prerelease SDK. This value will always be
+         * {@code REL} on production platform builds/devices.
+         *
+         * <p>When this value is not {@code REL}, it contains a string fingerprint of the API
+         * surface exposed by the preview SDK. Preview platforms with different API surfaces
+         * will have different {@code PREVIEW_SDK_FINGERPRINT}.
+         *
+         * <p>This attribute is intended for use by installers for finer grained targeting of
+         * packages. Applications targeting preview APIs should not use this field and should
+         * instead use {@code PREVIEW_SDK_INT} or use reflection or other runtime checks to
+         * detect the presence of an API or guard themselves against unexpected runtime
+         * behavior.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final String PREVIEW_SDK_FINGERPRINT = SystemProperties.get(
+                "ro.build.version.preview_sdk_fingerprint", "REL");
+
+        /**
          * The current development codename, or the string "REL" if this is
          * a release build.
          */
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index b0b8f49..f51ba9a 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -306,9 +306,18 @@
                                                 String packageName,
                                                 String paths,
                                                 String devOptIn) {
-        // Check for temporary rules if debuggable or root
-        if (!isDebuggable(context) && !(getCanLoadSystemLibraries() == 1)) {
-            Log.v(TAG, "Skipping loading temporary rules file");
+        /**
+         * We only want to load a temp rules file for:
+         *  - apps that are marked 'debuggable' in their manifest
+         *  - devices that are running a userdebug build (ro.debuggable) or can inject libraries for
+         *    debugging (PR_SET_DUMPABLE).
+         */
+        boolean appIsDebuggable = isDebuggable(context);
+        boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1;
+        if (!(appIsDebuggable || deviceIsDebuggable)) {
+            Log.v(TAG, "Skipping loading temporary rules file: "
+                    + "appIsDebuggable = " + appIsDebuggable + ", "
+                    + "adbRootEnabled = " + deviceIsDebuggable);
             return false;
         }
 
@@ -480,21 +489,36 @@
             return;
         }
 
-        if (getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_OUT_APPS)
-                        .contains(ai.packageName)) {
+        // GUP_DEV_ALL_APPS
+        // 0: Default (Invalid values fallback to default as well)
+        // 1: All apps use Game Update Package
+        // 2: All apps use system graphics driver
+        int gupDevAllApps = coreSettings.getInt(Settings.Global.GUP_DEV_ALL_APPS, 0);
+        if (gupDevAllApps == 2) {
             if (DEBUG) {
-                Log.w(TAG, ai.packageName + " opts out from GUP.");
+                Log.w(TAG, "GUP is turned off on this device");
             }
             return;
         }
 
-        if (!getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_IN_APPS)
-                        .contains(ai.packageName)
-                && !onWhitelist(context, driverPackageName, ai.packageName)) {
-            if (DEBUG) {
-                Log.w(TAG, ai.packageName + " is not on the whitelist.");
+        if (gupDevAllApps != 1) {
+            // GUP_DEV_OPT_OUT_APPS has higher priority than GUP_DEV_OPT_IN_APPS
+            if (getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_OUT_APPS)
+                            .contains(ai.packageName)) {
+                if (DEBUG) {
+                    Log.w(TAG, ai.packageName + " opts out from GUP.");
+                }
+                return;
             }
-            return;
+
+            if (!getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_IN_APPS)
+                            .contains(ai.packageName)
+                    && !onWhitelist(context, driverPackageName, ai.packageName)) {
+                if (DEBUG) {
+                    Log.w(TAG, ai.packageName + " is not on the whitelist.");
+                }
+                return;
+            }
         }
 
         ApplicationInfo driverInfo;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index fdd7488..8ced722 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -356,16 +356,6 @@
     void removeVpnUidRanges(int netId, in UidRange[] ranges);
 
     /**
-     * Start the clatd (464xlat) service on the given interface.
-     */
-    void startClatd(String interfaceName);
-
-    /**
-     * Stop the clatd (464xlat) service on the given interface.
-     */
-    void stopClatd(String interfaceName);
-
-    /**
      * Start listening for mobile activity state changes.
      */
     void registerNetworkActivityListener(INetworkActivityListener listener);
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index fb22194..23c54f4 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -16,23 +16,27 @@
 
 package android.os;
 
-import java.util.Map;
+import android.annotation.TestApi;
 
+import java.util.Map;
 
 /**
  * Java API for libvintf.
+ *
  * @hide
  */
+@TestApi
 public class VintfObject {
 
-    /// ---------- OTA
-
     /**
      * Slurps all device information (both manifests and both matrices)
      * and report them.
      * If any error in getting one of the manifests, it is not included in
      * the list.
+     *
+     * @hide
      */
+    @TestApi
     public static native String[] report();
 
     /**
@@ -44,6 +48,8 @@
      * @return = 0 if success (compatible)
      *         > 0 if incompatible
      *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     *
+     * @hide
      */
     public static native int verify(String[] packageInfo);
 
@@ -55,22 +61,28 @@
      * @return = 0 if success (compatible)
      *         > 0 if incompatible
      *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     *
+     * @hide
      */
     public static native int verifyWithoutAvb();
 
-    /// ---------- CTS Device Info
-
     /**
      * @return a list of HAL names and versions that is supported by this
      * device as stated in device and framework manifests. For example,
      * ["android.hidl.manager@1.0", "android.hardware.camera.device@1.0",
      *  "android.hardware.camera.device@3.2"]. There are no duplicates.
+     *
+     * @hide
      */
+    @TestApi
     public static native String[] getHalNamesAndVersions();
 
     /**
      * @return the BOARD_SEPOLICY_VERS build flag available in device manifest.
+     *
+     * @hide
      */
+    @TestApi
     public static native String getSepolicyVersion();
 
     /**
@@ -78,13 +90,22 @@
      * specified in framework manifest. For example,
      * [("27", ["libjpeg.so", "libbase.so"]),
      *  ("28", ["libjpeg.so", "libbase.so"])]
+     *
+     * @hide
      */
+    @TestApi
     public static native Map<String, String[]> getVndkSnapshots();
 
     /**
-     * @return target FCM version, a number specified in the device manifest
-     * indicating the FCM version that the device manifest implements. Null if
-     * device manifest doesn't specify this number (for legacy devices).
+     * @return Target Framework Compatibility Matrix (FCM) version, a number
+     * specified in the device manifest indicating the FCM version that the
+     * device manifest implements. Null if device manifest doesn't specify this
+     * number (for legacy devices).
+     *
+     * @hide
      */
+    @TestApi
     public static native Long getTargetFrameworkCompatibilityMatrixVersion();
+
+    private VintfObject() {}
 }
diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java
index 29698b9..f17039b 100644
--- a/core/java/android/os/VintfRuntimeInfo.java
+++ b/core/java/android/os/VintfRuntimeInfo.java
@@ -16,55 +16,84 @@
 
 package android.os;
 
+import android.annotation.TestApi;
+
 /**
  * Java API for ::android::vintf::RuntimeInfo. Methods return null / 0 on any error.
  *
  * @hide
  */
+@TestApi
 public class VintfRuntimeInfo {
 
     private VintfRuntimeInfo() {}
 
     /**
      * @return /sys/fs/selinux/policyvers, via security_policyvers() native call
+     *
+     * @hide
      */
     public static native long getKernelSepolicyVersion();
     /**
      * @return content of /proc/cpuinfo
+     *
+     * @hide
      */
+    @TestApi
     public static native String getCpuInfo();
     /**
      * @return os name extracted from uname() native call
+     *
+     * @hide
      */
+    @TestApi
     public static native String getOsName();
     /**
      * @return node name extracted from uname() native call
+     *
+     * @hide
      */
+    @TestApi
     public static native String getNodeName();
     /**
      * @return os release extracted from uname() native call
+     *
+     * @hide
      */
+    @TestApi
     public static native String getOsRelease();
     /**
      * @return os version extracted from uname() native call
+     *
+     * @hide
      */
+    @TestApi
     public static native String getOsVersion();
     /**
      * @return hardware id extracted from uname() native call
+     *
+     * @hide
      */
+    @TestApi
     public static native String getHardwareId();
     /**
      * @return kernel version extracted from uname() native call. Format is
      * {@code x.y.z}.
+     *
+     * @hide
      */
+    @TestApi
     public static native String getKernelVersion();
     /**
      * @return libavb version in OS. Format is {@code x.y}.
+     *
+     * @hide
      */
     public static native String getBootAvbVersion();
     /**
      * @return libavb version in bootloader. Format is {@code x.y}.
+     *
+     * @hide
      */
     public static native String getBootVbmetaAvbVersion();
-
 }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index c795895..af8146e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -16,9 +16,13 @@
 
 package android.provider;
 
+import static android.Manifest.permission.READ_DEVICE_CONFIG;
+import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
+
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.content.ContentResolver;
@@ -49,6 +53,13 @@
     public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config");
 
     /**
+     * Namespace for all Game Driver features.
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_GAME_DRIVER = "game_driver";
+
+    /**
      * Namespace for all input-related features that are used at the native level.
      * These features are applied at reboot.
      *
@@ -78,6 +89,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
     public static String getProperty(String namespace, String name) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
         String compositeName = createCompositeName(namespace, name);
@@ -105,6 +117,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(WRITE_DEVICE_CONFIG)
     public static boolean setProperty(
             String namespace, String name, String value, boolean makeDefault) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
@@ -125,6 +138,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(WRITE_DEVICE_CONFIG)
     public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) {
         ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
         Settings.Config.resetToDefaults(contentResolver, resetMode, namespace);
@@ -146,10 +160,12 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(READ_DEVICE_CONFIG)
     public static void addOnPropertyChangedListener(
             @NonNull String namespace,
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnPropertyChangedListener onPropertyChangedListener) {
+        // TODO enforce READ_DEVICE_CONFIG permission
         synchronized (sLock) {
             Pair<String, Executor> oldNamespace = sListeners.get(onPropertyChangedListener);
             if (oldNamespace == null) {
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 8e37559..e931826 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -34,6 +34,7 @@
 import android.graphics.fonts.FontStyle;
 import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
+import android.os.Build.VERSION_CODES;
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -651,7 +652,16 @@
                 if (familyBuilder == null) {
                     familyBuilder = new FontFamily.Builder(font);
                 } else {
-                    familyBuilder.addFont(font);
+                    try {
+                        familyBuilder.addFont(font);
+                    } catch (IllegalArgumentException e) {
+                        if (context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.P) {
+                            // Surpress the IllegalArgumentException for keeping the backward
+                            // compatibility.
+                            continue;
+                        }
+                        throw e;
+                    }
                 }
             } catch (IOException e) {
                 continue;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8482548..b39d871 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7391,6 +7391,14 @@
         private static final Validator DOZE_DOUBLE_TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
+         * Whether the device should respond to the SLPI tap gesture.
+         * @hide
+         */
+        public static final String DOZE_TAP_SCREEN_GESTURE = "doze_tap_gesture";
+
+        private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * Gesture that wakes up the lock screen.
          * @hide
          */
@@ -7724,6 +7732,23 @@
         public static final String TV_INPUT_CUSTOM_LABELS = "tv_input_custom_labels";
 
         /**
+         * Whether TV app uses non-system inputs.
+         *
+         * <p>
+         * The value is boolean (1 or 0), where 1 means non-system TV inputs are allowed,
+         * and 0 means non-system TV inputs are not allowed.
+         *
+         * <p>
+         * Devices such as sound bars may have changed the system property allow_third_party_inputs
+         * to false so the TV Application only uses HDMI and other built in inputs. This setting
+         * allows user to override the default and have the TV Application use third party TV inputs
+         * available on play store.
+         *
+         * @hide
+         */
+        public static final String TV_APP_USES_NON_SYSTEM_INPUTS = "tv_app_uses_non_system_inputs";
+
+        /**
          * Whether automatic routing of system audio to USB audio peripheral is disabled.
          * The value is boolean (1 or 0), where 1 means automatic routing is disabled,
          * and 0 means automatic routing is enabled.
@@ -8461,6 +8486,7 @@
             DOZE_ALWAYS_ON,
             DOZE_PICK_UP_GESTURE,
             DOZE_DOUBLE_TAP_GESTURE,
+            DOZE_TAP_SCREEN_GESTURE,
             DOZE_WAKE_LOCK_SCREEN_GESTURE,
             DOZE_WAKE_SCREEN_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
@@ -8617,6 +8643,7 @@
             VALIDATORS.put(DOZE_ALWAYS_ON, DOZE_ALWAYS_ON_VALIDATOR);
             VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
             VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
@@ -9381,6 +9408,15 @@
                 "hdmi_system_audio_control_enabled";
 
         /**
+         * Whether HDMI Routing Control feature is enabled. If enabled, the switch device will
+         * route to the correct input source on receiving Routing Control related messages. If
+         * disabled, you can only switch the input via controls on this device.
+         * @hide
+         */
+        public static final String HDMI_CEC_SWITCH_ENABLED =
+                "hdmi_cec_switch_enabled";
+
+        /**
          * Whether TV will automatically turn on upon reception of the CEC command
          * &lt;Text View On&gt; or &lt;Image View On&gt;. (0 = false, 1 = true)
          *
@@ -11082,6 +11118,31 @@
         /** {@hide} */
         public static final String
                 BLUETOOTH_HEARING_AID_PRIORITY_PREFIX = "bluetooth_hearing_aid_priority_";
+        /**
+         * Enable/disable radio bug detection
+         *
+         * {@hide}
+         */
+        public static final String
+                ENABLE_RADIO_BUG_DETECTION = "enable_radio_bug_detection";
+
+        /**
+         * Count threshold of RIL wakelock timeout for radio bug detection
+         *
+         * {@hide}
+         */
+        public static final String
+                RADIO_BUG_WAKELOCK_TIMEOUT_COUNT_THRESHOLD =
+                "radio_bug_wakelock_timeout_count_threshold";
+
+        /**
+         * Count threshold of RIL system error for radio bug detection
+         *
+         * {@hide}
+         */
+        public static final String
+                RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD =
+                "radio_bug_system_error_count_threshold";
 
         /**
          * Activity manager specific settings.
@@ -11572,6 +11633,7 @@
          * battery_level_collection_delay_ms (long)
          * max_history_files (int)
          * max_history_buffer_kb (int)
+         * battery_charged_delay_ms (int)
          * </pre>
          *
          * <p>
@@ -11957,22 +12019,33 @@
                 "angle_gl_driver_selection_values";
 
         /**
-         * List of Apps selected to use Game Update Packages.
+         * Game Update Package global preference for all Apps.
+         * 0 = Default
+         * 1 = All Apps use Game Update Package
+         * 2 = All Apps use system graphics driver
+         * @hide
+         */
+        public static final String GUP_DEV_ALL_APPS = "gup_dev_all_apps";
+
+        /**
+         * List of Apps selected to use Game Update Package.
+         * i.e. <pkg1>,<pkg2>,...,<pkgN>
          * @hide
          */
         public static final String GUP_DEV_OPT_IN_APPS = "gup_dev_opt_in_apps";
 
         /**
-         * List of Apps selected not to use Game Update Packages.
+         * List of Apps selected not to use Game Update Package.
+         * i.e. <pkg1>,<pkg2>,...,<pkgN>
          * @hide
          */
         public static final String GUP_DEV_OPT_OUT_APPS = "gup_dev_opt_out_apps";
 
         /**
-         * Apps on the black list that are forbidden to useGame Update Package.
+         * Apps on the blacklist that are forbidden to use Game Update Package.
          * @hide
          */
-        public static final String GUP_BLACK_LIST = "gup_black_list";
+        public static final String GUP_BLACKLIST = "gup_blacklist";
 
         /**
          * Ordered GPU debug layer list for Vulkan
@@ -14053,7 +14126,7 @@
          *
          * @hide
          */
-        // TODO(b/117663715): require a new read permission
+        @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
         static String getString(ContentResolver resolver, String name) {
             return sNameValueCache.getStringForUser(resolver, name, resolver.getUserId());
         }
@@ -14076,8 +14149,7 @@
          *
          * @hide
          */
-        // TODO(b/117663715): require a new write permission restricted to a single source
-        @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+        @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
         static boolean putString(@NonNull ContentResolver resolver, @NonNull String name,
                 @Nullable String value, boolean makeDefault) {
             return sNameValueCache.putStringForUser(resolver, name, value, null, makeDefault,
@@ -14099,7 +14171,7 @@
          * @hide
          */
         // TODO(b/117663715): require a new write permission restricted to a single source
-        @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+        @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
         static void resetToDefaults(@NonNull ContentResolver resolver, @ResetMode int resetMode,
                 @Nullable String prefix) {
             try {
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 0116961..aaba85b 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -42,6 +42,7 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAugmentedAutofillManagerClient;
+import android.view.autofill.IAutofillWindowPresenter;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -95,10 +96,10 @@
         }
 
         @Override
-        public void onDestroyFillWindowRequest(int sessionId) {
+        public void onDestroyAllFillWindowsRequest() {
             mHandler.sendMessage(
-                    obtainMessage(AugmentedAutofillService::handleOnDestroyFillWindowRequest,
-                            AugmentedAutofillService.this, sessionId));
+                    obtainMessage(AugmentedAutofillService::handleOnDestroyAllFillWindowsRequest,
+                            AugmentedAutofillService.this));
         }
     };
 
@@ -185,18 +186,21 @@
                 new FillCallback(proxy));
     }
 
-    private void handleOnDestroyFillWindowRequest(@NonNull int sessionId) {
-        AutofillProxy proxy = null;
+    private void handleOnDestroyAllFillWindowsRequest() {
         if (mAutofillProxies != null) {
-            proxy = mAutofillProxies.get(sessionId);
+            final int size = mAutofillProxies.size();
+            for (int i = 0; i < size; i++) {
+                final int sessionId = mAutofillProxies.keyAt(i);
+                final AutofillProxy proxy = mAutofillProxies.valueAt(i);
+                if (proxy == null) {
+                    // TODO(b/111330312): this might be fine, in which case we should logv it
+                    Log.w(TAG, "No proxy for session " + sessionId);
+                    return;
+                }
+                proxy.destroy();
+            }
+            mAutofillProxies.clear();
         }
-        if (proxy == null) {
-            // TODO(b/111330312): this might be fine, in which case we should logv it
-            Log.w(TAG, "No proxy for session " + sessionId);
-            return;
-        }
-        proxy.destroy();
-        mAutofillProxies.remove(sessionId);
     }
 
     private void handleOnUnbind() {
@@ -350,6 +354,16 @@
             }
         }
 
+        public void requestShowFillUi(int width, int height, Rect anchorBounds,
+                IAutofillWindowPresenter presenter) throws RemoteException {
+            mClient.requestShowFillUi(mSessionId, mFocusedId, width, height, anchorBounds,
+                    presenter);
+        }
+
+        public void requestHideFillUi() throws RemoteException {
+            mClient.requestHideFillUi(mSessionId, mFocusedId);
+        }
+
         private void update(@NonNull AutofillId focusedId, @NonNull AutofillValue focusedValue) {
             synchronized (mLock) {
                 // TODO(b/111330312): should we close the popupwindow if the focused id changed?
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 33b88e42..51b0f01 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -16,22 +16,25 @@
 package android.service.autofill.augmented;
 
 import static android.service.autofill.augmented.AugmentedAutofillService.DEBUG;
+import static android.service.autofill.augmented.AugmentedAutofillService.VERBOSE;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.app.Dialog;
 import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.RemoteException;
 import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
 import android.service.autofill.augmented.PresentationParams.Area;
 import android.util.Log;
-import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
 import android.view.WindowManager;
+import android.view.autofill.IAutofillWindowPresenter;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
@@ -71,7 +74,7 @@
     /** Indicates the data being shown is a physical address */
     public static final long FLAG_METADATA_ADDRESS = 0x1;
 
-    // TODO(b/111330312): add moar flags
+    // TODO(b/111330312): add more flags
 
     /** @hide */
     @LongDef(prefix = { "FLAG" }, value = {
@@ -83,8 +86,17 @@
     private final Object mLock = new Object();
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
+    private final @NonNull Handler mUiThreadHandler = new Handler(Looper.getMainLooper());
+    private final @NonNull FillWindowPresenter mFillWindowPresenter = new FillWindowPresenter();
+
     @GuardedBy("mLock")
-    private Dialog mDialog;
+    private WindowManager mWm;
+    @GuardedBy("mLock")
+    private View mFillView;
+    @GuardedBy("mLock")
+    private boolean mShowing;
+    @GuardedBy("mLock")
+    private Rect mBounds;
 
     @GuardedBy("mLock")
     private boolean mDestroyed;
@@ -140,51 +152,28 @@
             // window instead of destroying. In fact, it might be better to allocate a full window
             // initially, which is transparent (and let touches get through) everywhere but in the
             // rect boundaries.
-            destroy();
 
             // TODO(b/111330312): make sure all touch events are handled, window is always closed,
             // etc.
 
-            mDialog = new Dialog(rootView.getContext()) {
-                @Override
-                public boolean onTouchEvent(MotionEvent event) {
-                    if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
-                        FillWindow.this.destroy();
+            mWm = rootView.getContext().getSystemService(WindowManager.class);
+            mFillView = rootView;
+            // Listen to the touch outside to destroy the window when typing is detected.
+            mFillView.setOnTouchListener(
+                    (view, motionEvent) -> {
+                        if (motionEvent.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                            if (VERBOSE) Log.v(TAG, "Outside touch detected, hiding the window");
+                            hide();
+                        }
+                        return false;
                     }
-                    return false;
-                }
-            };
-            mCloseGuard.open("destroy");
-            final Window window = mDialog.getWindow();
-            window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
-            // Makes sure touch outside the dialog is received by the window behind the dialog.
-            window.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
-            // Makes sure the touch outside the dialog is received by the dialog to dismiss it.
-            window.addFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
-            // Makes sure keyboard shows up.
-            window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
-
-            final int height = rect.bottom - rect.top;
-            final int width = rect.right - rect.left;
-            final WindowManager.LayoutParams windowParams = window.getAttributes();
-            windowParams.gravity = Gravity.TOP | Gravity.LEFT;
-            windowParams.y = rect.top + height;
-            windowParams.height = height;
-            windowParams.x = rect.left;
-            windowParams.width = width;
-
-            window.setAttributes(windowParams);
-            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-            window.setBackgroundDrawableResource(android.R.color.transparent);
-
-            mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
-            final ViewGroup.LayoutParams diagParams = new ViewGroup.LayoutParams(width, height);
-            mDialog.setContentView(rootView, diagParams);
-
+            );
+            mShowing = false;
+            mBounds = new Rect(area.getBounds());
             if (DEBUG) {
                 Log.d(TAG, "Created FillWindow: params= " + smartSuggestion + " view=" + rootView);
             }
-
+            mDestroyed = false;
             mProxy.setFillWindow(this);
             return true;
         }
@@ -194,36 +183,87 @@
     void show() {
         // TODO(b/111330312): check if updated first / throw exception
         if (DEBUG) Log.d(TAG, "show()");
-
         synchronized (mLock) {
             checkNotDestroyedLocked();
-            if (mDialog == null) {
+            if (mWm == null || mFillView == null) {
                 throw new IllegalStateException("update() not called yet, or already destroyed()");
             }
-
-            mDialog.show();
             if (mProxy != null) {
+                try {
+                    mProxy.requestShowFillUi(mBounds.right - mBounds.left,
+                            mBounds.bottom - mBounds.top,
+                            /*anchorBounds=*/ null, mFillWindowPresenter);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error requesting to show fill window", e);
+                }
                 mProxy.report(AutofillProxy.REPORT_EVENT_UI_SHOWN);
             }
         }
     }
 
     /**
+     * Hides the window.
+     *
+     * <p>The window is not destroyed and can be shown again
+     */
+    private void hide() {
+        if (DEBUG) Log.d(TAG, "hide()");
+        synchronized (mLock) {
+            checkNotDestroyedLocked();
+            if (mWm == null || mFillView == null) {
+                throw new IllegalStateException("update() not called yet, or already destroyed()");
+            }
+            if (mProxy != null && mShowing) {
+                try {
+                    mProxy.requestHideFillUi();
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Error requesting to hide fill window", e);
+                }
+            }
+        }
+    }
+
+    private void handleShow(WindowManager.LayoutParams p) {
+        if (DEBUG) Log.d(TAG, "handleShow()");
+        synchronized (mLock) {
+            if (mWm != null && mFillView != null) {
+                p.flags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+                if (!mShowing) {
+                    mWm.addView(mFillView, p);
+                    mShowing = true;
+                } else {
+                    mWm.updateViewLayout(mFillView, p);
+                }
+            }
+        }
+    }
+
+    private void handleHide() {
+        if (DEBUG) Log.d(TAG, "handleHide()");
+        synchronized (mLock) {
+            if (mWm != null && mFillView != null && mShowing) {
+                mWm.removeView(mFillView);
+                mShowing = false;
+            }
+        }
+    }
+
+    /**
      * Destroys the window.
      *
      * <p>Once destroyed, this window cannot be used anymore
      */
     public void destroy() {
-        if (DEBUG) Log.d(TAG, "destroy(): mDestroyed=" + mDestroyed + " mDialog=" + mDialog);
-
-        synchronized (this) {
-            if (mDestroyed || mDialog == null) return;
-
-            mDialog.dismiss();
-            mDialog = null;
-            if (mProxy != null) {
-                mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
-            }
+        if (DEBUG) {
+            Log.d(TAG,
+                    "destroy(): mDestroyed=" + mDestroyed + " mShowing=" + mShowing + " mFillView="
+                            + mFillView);
+        }
+        synchronized (mLock) {
+            if (mDestroyed) return;
+            hide();
+            mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
+            mDestroyed = true;
             mCloseGuard.close();
         }
     }
@@ -250,11 +290,15 @@
     public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
         synchronized (this) {
             pw.print(prefix); pw.print("destroyed: "); pw.println(mDestroyed);
-            if (mDialog != null) {
-                pw.print(prefix); pw.print("dialog: ");
-                pw.println(mDialog.isShowing() ? "shown" : "hidden");
-                pw.print(prefix); pw.print("window: ");
-                pw.println(mDialog.getWindow().getAttributes());
+            if (mFillView != null) {
+                pw.print(prefix); pw.print("fill window: ");
+                pw.println(mShowing ? "shown" : "hidden");
+                pw.print(prefix); pw.print("fill view: ");
+                pw.println(mFillView);
+                pw.print(prefix); pw.print("mBounds: ");
+                pw.println(mBounds);
+                pw.print(prefix); pw.print("mWm: ");
+                pw.println(mWm);
             }
         }
     }
@@ -264,4 +308,19 @@
     public void close() throws Exception {
         destroy();
     }
+
+    private final class FillWindowPresenter extends IAutofillWindowPresenter.Stub {
+        @Override
+        public void show(WindowManager.LayoutParams p, Rect transitionEpicenter,
+                boolean fitsSystemWindows, int layoutDirection) {
+            if (DEBUG) Log.d(TAG, "FillWindowPresenter.show()");
+            mUiThreadHandler.sendMessage(obtainMessage(FillWindow::handleShow, FillWindow.this, p));
+        }
+
+        @Override
+        public void hide(Rect transitionEpicenter) {
+            if (DEBUG) Log.d(TAG, "FillWindowPresenter.hide()");
+            mUiThreadHandler.sendMessage(obtainMessage(FillWindow::handleHide, FillWindow.this));
+        }
+    }
 }
diff --git a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
index b3ac2da1..fb6912a 100644
--- a/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
+++ b/core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl
@@ -36,5 +36,5 @@
                        in ComponentName activityComponent, in AutofillId focusedId,
                        in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
 
-    void onDestroyFillWindowRequest(int sessionId);
+    void onDestroyAllFillWindowsRequest();
 }
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index e5e028d..302e1a6 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -48,6 +48,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -77,6 +78,7 @@
             "android.service.contentcapture.ContentCaptureService";
 
     private Handler mHandler;
+    private IContentCaptureServiceCallback mCallback;
 
     /**
      * Binder that receives calls from the system server.
@@ -84,9 +86,15 @@
     private final IContentCaptureService mServerInterface = new IContentCaptureService.Stub() {
 
         @Override
-        public void onConnectedStateChanged(boolean state) {
-            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnConnectedStateChanged,
-                    ContentCaptureService.this, state));
+        public void onConnected(IBinder callback) {
+            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnConnected,
+                    ContentCaptureService.this, callback));
+        }
+
+        @Override
+        public void onDisconnected() {
+            mHandler.sendMessage(obtainMessage(ContentCaptureService::handleOnDisconnected,
+                    ContentCaptureService.this));
         }
 
         @Override
@@ -166,7 +174,16 @@
      */
     public final void setContentCaptureWhitelist(@Nullable List<String> packages,
             @Nullable List<ComponentName> activities) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setContentCaptureWhitelist(): no server callback");
+            return;
+        }
+        try {
+            callback.setContentCaptureWhitelist(packages, activities);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -177,7 +194,16 @@
      */
     public final void setActivityContentCaptureEnabled(@NonNull ComponentName activity,
             boolean enabled) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setActivityContentCaptureEnabled(): no server callback");
+            return;
+        }
+        try {
+            callback.setActivityContentCaptureEnabled(activity, enabled);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -188,7 +214,16 @@
      */
     public final void setPackageContentCaptureEnabled(@NonNull String packageName,
             boolean enabled) {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "setPackageContentCaptureEnabled(): no server callback");
+            return;
+        }
+        try {
+            callback.setPackageContentCaptureEnabled(packageName, enabled);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -197,7 +232,12 @@
      */
     @NonNull
     public final Set<ComponentName> getContentCaptureDisabledActivities() {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "getContentCaptureDisabledActivities(): no server callback");
+            return Collections.emptySet();
+        }
+        //TODO(b/122595322): implement (using SyncResultReceiver)
         return null;
     }
 
@@ -207,7 +247,12 @@
      */
     @NonNull
     public final Set<String> getContentCaptureDisabledPackages() {
-        //TODO(b/122595322): implement
+        final IContentCaptureServiceCallback callback = mCallback;
+        if (callback == null) {
+            Log.w(TAG, "getContentCaptureDisabledPackages(): no server callback");
+            return Collections.emptySet();
+        }
+        //TODO(b/122595322): implement (using SyncResultReceiver)
         return null;
     }
 
@@ -307,12 +352,14 @@
         }
     }
 
-    private void handleOnConnectedStateChanged(boolean state) {
-        if (state) {
-            onConnected();
-        } else {
-            onDisconnected();
-        }
+    private void handleOnConnected(@NonNull IBinder callback) {
+        mCallback = IContentCaptureServiceCallback.Stub.asInterface(callback);
+        onConnected();
+    }
+
+    private void handleOnDisconnected() {
+        onDisconnected();
+        mCallback = null;
     }
 
     //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
@@ -323,15 +370,21 @@
         mSessionUids.put(sessionId, uid);
         onCreateContentCaptureSession(context, new ContentCaptureSessionId(sessionId));
 
-        final int flags = context.getFlags();
-        if ((flags & ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE) != 0) {
-            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_BY_FLAG_SECURE,
-                    mClientInterface.asBinder());
-            return;
+        final int clientFlags = context.getFlags();
+        int stateFlags = 0;
+        if ((clientFlags & ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE) != 0) {
+            stateFlags |= ContentCaptureSession.STATE_FLAG_SECURE;
         }
+        if ((clientFlags & ContentCaptureContext.FLAG_DISABLED_BY_APP) != 0) {
+            stateFlags |= ContentCaptureSession.STATE_BY_APP;
+        }
+        if (stateFlags == 0) {
+            stateFlags = ContentCaptureSession.STATE_ACTIVE;
+        } else {
+            stateFlags |= ContentCaptureSession.STATE_DISABLED;
 
-        setClientState(clientReceiver, ContentCaptureSession.STATE_ACTIVE,
-                mClientInterface.asBinder());
+        }
+        setClientState(clientReceiver, stateFlags, mClientInterface.asBinder());
     }
 
     private void handleSendEvents(int uid,
diff --git a/core/java/android/service/contentcapture/IContentCaptureService.aidl b/core/java/android/service/contentcapture/IContentCaptureService.aidl
index 1b4cccf..a8dd213 100644
--- a/core/java/android/service/contentcapture/IContentCaptureService.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureService.aidl
@@ -16,6 +16,7 @@
 
 package android.service.contentcapture;
 
+import android.os.IBinder;
 import android.service.contentcapture.SnapshotData;
 import android.view.contentcapture.ContentCaptureContext;
 
@@ -29,7 +30,8 @@
  * @hide
  */
 oneway interface IContentCaptureService {
-    void onConnectedStateChanged(boolean state);
+    void onConnected(IBinder callback);
+    void onDisconnected();
     void onSessionStarted(in ContentCaptureContext context, String sessionId, int uid,
                           in IResultReceiver clientReceiver);
     void onSessionFinished(String sessionId);
diff --git a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
new file mode 100644
index 0000000..e84bd6f
--- /dev/null
+++ b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.contentcapture;
+
+import android.content.ComponentName;
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * Interface from the Content Capture service to the system.
+ *
+ * @hide
+ */
+oneway interface IContentCaptureServiceCallback {
+    void setContentCaptureWhitelist(in List<String> packages, in List<ComponentName> activities);
+    void setActivityContentCaptureEnabled(in ComponentName activity, boolean enabled);
+    void setPackageContentCaptureEnabled(in String packageName, boolean enabled);
+    void getContentCaptureDisabledActivities(in IResultReceiver receiver);
+    void getContentCaptureDisabledPackages(in IResultReceiver receiver);
+}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 163e3d5..6f27447 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -121,6 +121,12 @@
      */
     public static final int SHOW_SOURCE_NOTIFICATION = 1 << 6;
 
+    /**
+     * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked
+     * from an Android automotive system Ui.
+     */
+    public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7;
+
     final Context mContext;
     final HandlerCaller mHandlerCaller;
 
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 85b6b88..44353b1 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -33,8 +33,7 @@
 import android.icu.util.ULocale;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemProperties;
-import android.provider.Settings;
+import android.sysprop.DisplayProperties;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AccessibilityClickableSpan;
 import android.text.style.AccessibilityURLSpan;
@@ -2059,7 +2058,7 @@
         return ((locale != null && !locale.equals(Locale.ROOT)
                         && ULocale.forLocale(locale).isRightToLeft())
                 // If forcing into RTL layout mode, return RTL as default
-                || SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false))
+                || DisplayProperties.debug_force_rtl().orElse(false))
             ? View.LAYOUT_DIRECTION_RTL
             : View.LAYOUT_DIRECTION_LTR;
     }
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index ea4464d..99106be 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -216,6 +216,12 @@
      * */
     public int density;
 
+    /**
+     * If the Value came from a style resource, this holds the corresponding style resource id
+     * against which the attribute was resolved.
+     */
+    public int sourceStyleResourceId;
+
     /* ------------------------------------------------------------ */
 
     /** Return the data for this value as a float.  Only use for values
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index ffd4156..dc7c343 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -22,6 +22,7 @@
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
@@ -29,6 +30,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -38,6 +40,9 @@
 
 import com.android.internal.R;
 
+import dalvik.system.PathClassLoader;
+import java.io.File;
+import java.lang.reflect.Method;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -72,6 +77,10 @@
     private static final String TAG = LayoutInflater.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY
+        = "view.precompiled_layout_enabled";
+    private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex";
+
     /** Empty stack trace used to avoid log spam in re-throw exceptions. */
     private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];
 
@@ -93,6 +102,13 @@
     private Factory2 mPrivateFactory;
     private Filter mFilter;
 
+    // Indicates whether we should try to inflate layouts using a precompiled layout instead of
+    // inflating from the XML resource.
+    private boolean mUseCompiledView;
+    // This variable holds the classloader that will be used to look for precompiled layouts. The
+    // The classloader includes the generated compiled_view.dex file.
+    private ClassLoader mPrecompiledClassLoader;
+
     @UnsupportedAppUsage
     final Object[] mConstructorArgs = new Object[2];
 
@@ -223,6 +239,7 @@
      */
     protected LayoutInflater(Context context) {
         mContext = context;
+        initPrecompiledViews();
     }
 
     /**
@@ -239,6 +256,7 @@
         mFactory2 = original.mFactory2;
         mPrivateFactory = original.mPrivateFactory;
         setFilter(original.mFilter);
+        initPrecompiledViews();
     }
 
     /**
@@ -380,6 +398,41 @@
         }
     }
 
+    private void initPrecompiledViews() {
+        // Check if precompiled layouts are enabled by a system property.
+        mUseCompiledView =
+            SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
+        if (!mUseCompiledView) {
+            return;
+        }
+
+        // Make sure the application allows code generation
+        ApplicationInfo appInfo = mContext.getApplicationInfo();
+        if ((appInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY) != 0
+            || appInfo.isPrivilegedApp()) {
+            mUseCompiledView = false;
+            return;
+        }
+
+        // Try to load the precompiled layout file.
+        try {
+            mPrecompiledClassLoader = mContext.getClassLoader();
+            String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME;
+            if (new File(dexFile).exists()) {
+                mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader);
+            } else {
+                // If the precompiled layout file doesn't exist, then disable precompiled
+                // layouts.
+                mUseCompiledView = false;
+            }
+        } catch (Throwable e) {
+            if (DEBUG) {
+                Log.e(TAG, "Failed to initialized precompiled views layouts", e);
+            }
+            mUseCompiledView = false;
+        }
+    }
+
     /**
      * Inflate a new view hierarchy from the specified xml resource. Throws
      * {@link InflateException} if there is an error.
@@ -436,10 +489,14 @@
         final Resources res = getContext().getResources();
         if (DEBUG) {
             Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
-                    + Integer.toHexString(resource) + ")");
+                  + Integer.toHexString(resource) + ")");
         }
 
-        final XmlResourceParser parser = res.getLayout(resource);
+        View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
+        if (view != null) {
+            return view;
+        }
+        XmlResourceParser parser = res.getLayout(resource);
         try {
             return inflate(parser, root, attachToRoot);
         } finally {
@@ -447,6 +504,73 @@
         }
     }
 
+    private @Nullable
+    View tryInflatePrecompiled(@LayoutRes int resource, Resources res, @Nullable ViewGroup root,
+        boolean attachToRoot) {
+        if (!mUseCompiledView) {
+            return null;
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate (precompiled)");
+
+        // Try to inflate using a precompiled layout.
+        String pkg = res.getResourcePackageName(resource);
+        String layout = res.getResourceEntryName(resource);
+
+        try {
+            Class clazz = mPrecompiledClassLoader.loadClass("" + pkg + ".CompiledView");
+            Method inflater = clazz.getMethod(layout, Context.class, int.class);
+            View view = (View) inflater.invoke(null, mContext, resource);
+
+            if (view != null && root != null) {
+                // We were able to use the precompiled inflater, but now we need to do some work to
+                // attach the view to the root correctly.
+                XmlResourceParser parser = res.getLayout(resource);
+                try {
+                    AttributeSet attrs = Xml.asAttributeSet(parser);
+                    advanceToRootNode(parser);
+                    ViewGroup.LayoutParams params = root.generateLayoutParams(attrs);
+
+                    if (attachToRoot) {
+                        root.addView(view, params);
+                    } else {
+                        view.setLayoutParams(params);
+                    }
+                } finally {
+                    parser.close();
+                }
+            }
+
+            return view;
+        } catch (Throwable e) {
+            if (DEBUG) {
+                Log.e(TAG, "Failed to use precompiled view", e);
+            }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
+        return null;
+    }
+
+    /**
+     * Advances the given parser to the first START_TAG. Throws InflateException if no start tag is
+     * found.
+     */
+    private void advanceToRootNode(XmlPullParser parser)
+        throws InflateException, IOException, XmlPullParserException {
+        // Look for the root node.
+        int type;
+        while ((type = parser.next()) != XmlPullParser.START_TAG &&
+            type != XmlPullParser.END_DOCUMENT) {
+            // Empty
+        }
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new InflateException(parser.getPositionDescription()
+                + ": No start tag found!");
+        }
+    }
+
     /**
      * Inflate a new view hierarchy from the specified XML node. Throws
      * {@link InflateException} if there is an error.
@@ -480,18 +604,7 @@
             View result = root;
 
             try {
-                // Look for the root node.
-                int type;
-                while ((type = parser.next()) != XmlPullParser.START_TAG &&
-                        type != XmlPullParser.END_DOCUMENT) {
-                    // Empty
-                }
-
-                if (type != XmlPullParser.START_TAG) {
-                    throw new InflateException(parser.getPositionDescription()
-                            + ": No start tag found!");
-                }
-
+                advanceToRootNode(parser);
                 final String name = parser.getName();
 
                 if (DEBUG) {
@@ -994,82 +1107,85 @@
                 + "reference. The layout ID " + value + " is not valid.");
         }
 
-        final XmlResourceParser childParser = context.getResources().getLayout(layout);
+        final View precompiled = tryInflatePrecompiled(layout, context.getResources(),
+            (ViewGroup) parent, /*attachToRoot=*/true);
+        if (precompiled == null) {
+            final XmlResourceParser childParser = context.getResources().getLayout(layout);
 
-        try {
-            final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
+            try {
+                final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
 
-            while ((type = childParser.next()) != XmlPullParser.START_TAG &&
-                type != XmlPullParser.END_DOCUMENT) {
-                // Empty.
+                while ((type = childParser.next()) != XmlPullParser.START_TAG &&
+                    type != XmlPullParser.END_DOCUMENT) {
+                    // Empty.
+                }
+
+                if (type != XmlPullParser.START_TAG) {
+                    throw new InflateException(childParser.getPositionDescription() +
+                        ": No start tag found!");
+                }
+
+                final String childName = childParser.getName();
+
+                if (TAG_MERGE.equals(childName)) {
+                    // The <merge> tag doesn't support android:theme, so
+                    // nothing special to do here.
+                    rInflate(childParser, parent, context, childAttrs, false);
+                } else {
+                    final View view = createViewFromTag(parent, childName,
+                        context, childAttrs, hasThemeOverride);
+                    final ViewGroup group = (ViewGroup) parent;
+
+                    final TypedArray a = context.obtainStyledAttributes(
+                        attrs, R.styleable.Include);
+                    final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
+                    final int visibility = a.getInt(R.styleable.Include_visibility, -1);
+                    a.recycle();
+
+                    // We try to load the layout params set in the <include /> tag.
+                    // If the parent can't generate layout params (ex. missing width
+                    // or height for the framework ViewGroups, though this is not
+                    // necessarily true of all ViewGroups) then we expect it to throw
+                    // a runtime exception.
+                    // We catch this exception and set localParams accordingly: true
+                    // means we successfully loaded layout params from the <include>
+                    // tag, false means we need to rely on the included layout params.
+                    ViewGroup.LayoutParams params = null;
+                    try {
+                        params = group.generateLayoutParams(attrs);
+                    } catch (RuntimeException e) {
+                        // Ignore, just fail over to child attrs.
+                    }
+                    if (params == null) {
+                        params = group.generateLayoutParams(childAttrs);
+                    }
+                    view.setLayoutParams(params);
+
+                    // Inflate all children.
+                    rInflateChildren(childParser, view, childAttrs, true);
+
+                    if (id != View.NO_ID) {
+                        view.setId(id);
+                    }
+
+                    switch (visibility) {
+                        case 0:
+                            view.setVisibility(View.VISIBLE);
+                            break;
+                        case 1:
+                            view.setVisibility(View.INVISIBLE);
+                            break;
+                        case 2:
+                            view.setVisibility(View.GONE);
+                            break;
+                    }
+
+                    group.addView(view);
+                }
+            } finally {
+                childParser.close();
             }
-
-            if (type != XmlPullParser.START_TAG) {
-                throw new InflateException(childParser.getPositionDescription() +
-                    ": No start tag found!");
-            }
-
-            final String childName = childParser.getName();
-
-            if (TAG_MERGE.equals(childName)) {
-                // The <merge> tag doesn't support android:theme, so
-                // nothing special to do here.
-                rInflate(childParser, parent, context, childAttrs, false);
-            } else {
-                final View view = createViewFromTag(parent, childName,
-                    context, childAttrs, hasThemeOverride);
-                final ViewGroup group = (ViewGroup) parent;
-
-                final TypedArray a = context.obtainStyledAttributes(
-                    attrs, R.styleable.Include);
-                final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID);
-                final int visibility = a.getInt(R.styleable.Include_visibility, -1);
-                a.recycle();
-
-                // We try to load the layout params set in the <include /> tag.
-                // If the parent can't generate layout params (ex. missing width
-                // or height for the framework ViewGroups, though this is not
-                // necessarily true of all ViewGroups) then we expect it to throw
-                // a runtime exception.
-                // We catch this exception and set localParams accordingly: true
-                // means we successfully loaded layout params from the <include>
-                // tag, false means we need to rely on the included layout params.
-                ViewGroup.LayoutParams params = null;
-                try {
-                    params = group.generateLayoutParams(attrs);
-                } catch (RuntimeException e) {
-                    // Ignore, just fail over to child attrs.
-                }
-                if (params == null) {
-                    params = group.generateLayoutParams(childAttrs);
-                }
-                view.setLayoutParams(params);
-
-                // Inflate all children.
-                rInflateChildren(childParser, view, childAttrs, true);
-
-                if (id != View.NO_ID) {
-                    view.setId(id);
-                }
-
-                switch (visibility) {
-                    case 0:
-                        view.setVisibility(View.VISIBLE);
-                        break;
-                    case 1:
-                        view.setVisibility(View.INVISIBLE);
-                        break;
-                    case 2:
-                        view.setVisibility(View.GONE);
-                        break;
-                }
-
-                group.addView(view);
-            }
-        } finally {
-            childParser.close();
         }
-
         LayoutInflater.consumeChildElements(parser);
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ff5120d..273d89c 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -167,6 +167,7 @@
             InputWindowHandle handle);
     private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken,
             IBinder toToken);
+    private static native boolean nativeGetProtectedContentSupport();
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -1730,6 +1731,14 @@
     }
 
     /**
+     * Returns whether protected content is supported in GPU composition.
+     * @hide
+     */
+    public static boolean getProtectedContentSupport() {
+        return nativeGetProtectedContentSupport();
+    }
+
+    /**
      * @hide
      */
     public static class Transaction implements Closeable {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index abefd55..32974ac 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -76,8 +76,8 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.Trace;
+import android.sysprop.DisplayProperties;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -812,14 +812,6 @@
     private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
 
     /**
-     * When set to true, apps will draw debugging information about their layouts.
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
-
-    /**
      * When set to true, this view will save its attribute data.
      *
      * @hide
@@ -27833,7 +27825,7 @@
         /**
          * Show where the margins, bounds and layout bounds are for each view.
          */
-        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
+        boolean mDebugLayout = DisplayProperties.debug_layout().orElse(false);
 
         /**
          * Point used to compute visible regions.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8e4dc67..27d4ea4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -75,6 +75,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
+import android.sysprop.DisplayProperties;
 import android.util.AndroidRuntimeException;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -7071,7 +7072,7 @@
                 }
 
                 // Layout debugging
-                boolean layout = SystemProperties.getBoolean(View.DEBUG_LAYOUT_PROPERTY, false);
+                boolean layout = DisplayProperties.debug_layout().orElse(false);
                 if (layout != mAttachInfo.mDebugLayout) {
                     mAttachInfo.mDebugLayout = layout;
                     if (!mHandler.hasMessages(MSG_INVALIDATE_WORLD)) {
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index c630177..dfd9a2e 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -187,6 +187,7 @@
     /**
      * An animation listener to be notified when the animation starts, ends or repeats.
      */
+    @UnsupportedAppUsage
     private AnimationListener mListener;
 
     /**
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 93941d0..888a4c5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -2997,5 +2997,23 @@
                 afm.post(() -> afm.autofill(sessionId, ids, values));
             }
         }
+
+        @Override
+        public void requestShowFillUi(int sessionId, AutofillId id, int width, int height,
+                Rect anchorBounds, IAutofillWindowPresenter presenter) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.post(() -> afm.requestShowFillUi(sessionId, id, width, height, anchorBounds,
+                        presenter));
+            }
+        }
+
+        @Override
+        public void requestHideFillUi(int sessionId, AutofillId id) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.post(() -> afm.requestHideFillUi(id, false));
+            }
+        }
     }
 }
diff --git a/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl b/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl
index 67cd0bf..140507c 100644
--- a/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl
@@ -21,6 +21,7 @@
 import android.graphics.Rect;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
+import android.view.autofill.IAutofillWindowPresenter;
 
 /**
  * Object running in the application process and responsible to provide the functionalities
@@ -29,6 +30,24 @@
  * @hide
  */
 interface IAugmentedAutofillManagerClient {
-   Rect getViewCoordinates(in AutofillId id);
-   void autofill(int sessionId, in List<AutofillId> ids, in List<AutofillValue> values);
+    /**
+      * Gets the coordinates of the input field view.
+      */
+    Rect getViewCoordinates(in AutofillId id);
+
+    /**
+     * Autofills the activity with the contents of the values.
+     */
+    void autofill(int sessionId, in List<AutofillId> ids, in List<AutofillValue> values);
+
+    /**
+      * Requests showing the fill UI.
+      */
+    void requestShowFillUi(int sessionId, in AutofillId id, int width, int height,
+            in Rect anchorBounds, in IAutofillWindowPresenter presenter);
+
+    /**
+      * Requests hiding the fill UI.
+      */
+    void requestHideFillUi(int sessionId, in AutofillId id);
 }
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 04e725e..cb4c4b4 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -68,8 +68,8 @@
     }
 
     @Override
-    void flush() {
-        mParent.flush();
+    void flush(@FlushReason int reason) {
+        mParent.flush(reason);
     }
 
     @Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index ff45efd..413f1a5 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -24,17 +24,18 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.contentcapture.ContentCaptureSession.FlushReason;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.SyncResultReceiver;
 
 import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /*
  * NOTE: all methods in this class should return right away, or do the real work in a handler
@@ -51,8 +52,6 @@
 
     private static final String TAG = ContentCaptureManager.class.getSimpleName();
 
-    private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
-
     /**
      * Timeout for calls to system_server.
      */
@@ -62,8 +61,10 @@
     static final boolean VERBOSE = false;
     static final boolean DEBUG = true; // STOPSHIP if not set to false
 
-    @NonNull
-    private final AtomicBoolean mDisabled = new AtomicBoolean();
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private boolean mDisabled;
 
     @NonNull
     private final Context mContext;
@@ -71,35 +72,29 @@
     @Nullable
     private final IContentCaptureManager mService;
 
+    // Flags used for starting session.
+    @GuardedBy("mLock")
+    private int mFlags;
+
     // TODO(b/119220549): use UI Thread directly (as calls are one-way) or a shared thread / handler
     // held at the Application level
     @NonNull
     private final Handler mHandler;
 
+    @GuardedBy("mLock")
     private MainContentCaptureSession mMainSession;
 
     /** @hide */
     public ContentCaptureManager(@NonNull Context context,
             @Nullable IContentCaptureManager service) {
         mContext = Preconditions.checkNotNull(context, "context cannot be null");
-        if (VERBOSE) {
-            Log.v(TAG, "Constructor for " + context.getPackageName());
-        }
-        mService = service;
-        // TODO(b/119220549): use an existing bg thread instead...
-        final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
-        bgThread.start();
-        mHandler = Handler.createAsync(bgThread.getLooper());
-    }
+        if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName());
 
-    @NonNull
-    private static Handler newHandler() {
-        // TODO(b/119220549): use an existing bg thread instead...
-        // TODO(b/119220549): use UI Thread directly (as calls are one-way) or an existing bgThread
-        // or a shared thread / handler held at the Application level
-        final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
-        bgThread.start();
-        return Handler.createAsync(bgThread.getLooper());
+        mService = service;
+        // TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we
+        // do, then we should optimize it to run the tests after the Choreographer finishes the most
+        // important steps of the frame.
+        mHandler = Handler.createAsync(Looper.getMainLooper());
     }
 
     /**
@@ -114,20 +109,25 @@
     @NonNull
     @UiThread
     public MainContentCaptureSession getMainContentCaptureSession() {
-        if (mMainSession == null) {
-            mMainSession = new MainContentCaptureSession(mContext, mHandler, mService,
-                    mDisabled);
-            if (VERBOSE) {
-                Log.v(TAG, "getDefaultContentCaptureSession(): created " + mMainSession);
+        synchronized (mLock) {
+            if (mMainSession == null) {
+                mMainSession = new MainContentCaptureSession(mContext, mHandler, mService,
+                        mDisabled);
+                if (VERBOSE) {
+                    Log.v(TAG, "getDefaultContentCaptureSession(): created " + mMainSession);
+                }
             }
+            return mMainSession;
         }
-        return mMainSession;
     }
 
     /** @hide */
     public void onActivityStarted(@NonNull IBinder applicationToken,
             @NonNull ComponentName activityComponent, int flags) {
-        getMainContentCaptureSession().start(applicationToken, activityComponent, flags);
+        synchronized (mLock) {
+            mFlags |= flags;
+            getMainContentCaptureSession().start(applicationToken, activityComponent, mFlags);
+        }
     }
 
     /** @hide */
@@ -142,8 +142,8 @@
      *
      * @hide
      */
-    public void flush() {
-        getMainContentCaptureSession().flush();
+    public void flush(@FlushReason int reason) {
+        getMainContentCaptureSession().flush(reason);
     }
 
     /**
@@ -173,7 +173,9 @@
      * Checks whether content capture is enabled for this activity.
      */
     public boolean isContentCaptureEnabled() {
-        return mService != null && !mDisabled.get();
+        synchronized (mLock) {
+            return mService != null && !mDisabled;
+        }
     }
 
     /**
@@ -183,7 +185,9 @@
      * it on {@link android.app.Activity#onCreate(android.os.Bundle, android.os.PersistableBundle)}.
      */
     public void setContentCaptureEnabled(boolean enabled) {
-        //TODO(b/111276913): implement (need to finish / disable all sessions)
+        synchronized (mLock) {
+            mFlags |= enabled ? 0 : ContentCaptureContext.FLAG_DISABLED_BY_APP;
+        }
     }
 
     /**
@@ -198,20 +202,22 @@
 
     /** @hide */
     public void dump(String prefix, PrintWriter pw) {
-        pw.print(prefix); pw.println("ContentCaptureManager");
-
-        pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled.get());
-        pw.print(prefix); pw.print("Context: "); pw.println(mContext);
-        pw.print(prefix); pw.print("User: "); pw.println(mContext.getUserId());
-        if (mService != null) {
-            pw.print(prefix); pw.print("Service: "); pw.println(mService);
-        }
-        if (mMainSession != null) {
-            final String prefix2 = prefix + "  ";
-            pw.print(prefix); pw.println("Main session:");
-            mMainSession.dump(prefix2, pw);
-        } else {
-            pw.print(prefix); pw.println("No sessions");
+        synchronized (mLock) {
+            pw.print(prefix); pw.println("ContentCaptureManager");
+            pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
+            pw.print(prefix); pw.print("Context: "); pw.println(mContext);
+            pw.print(prefix); pw.print("User: "); pw.println(mContext.getUserId());
+            if (mService != null) {
+                pw.print(prefix); pw.print("Service: "); pw.println(mService);
+            }
+            pw.print(prefix); pw.print("Flags: "); pw.println(mFlags);
+            if (mMainSession != null) {
+                final String prefix2 = prefix + "  ";
+                pw.print(prefix); pw.println("Main session:");
+                mMainSession.dump(prefix2, pw);
+            } else {
+                pw.print(prefix); pw.println("No sessions");
+            }
         }
     }
 
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index d9a8416..a9e7b5e 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -19,8 +19,10 @@
 import static android.view.contentcapture.ContentCaptureManager.VERBOSE;
 
 import android.annotation.CallSuper;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.DebugUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewStructure;
@@ -34,6 +36,8 @@
 import dalvik.system.CloseGuard;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.UUID;
 
@@ -56,45 +60,100 @@
      *
      * @hide
      */
-    public static final int STATE_UNKNOWN = 0;
+    // NOTE: not prefixed by STATE_ so it's not printed on getStateAsString()
+    public static final int UNKNWON_STATE = 0x0;
 
     /**
      * Service's startSession() was called, but server didn't confirm it was created yet.
      *
      * @hide
      */
-    public static final int STATE_WAITING_FOR_SERVER = 1;
+    public static final int STATE_WAITING_FOR_SERVER = 0x1;
 
     /**
      * Session is active.
      *
      * @hide
      */
-    public static final int STATE_ACTIVE = 2;
+    public static final int STATE_ACTIVE = 0x2;
 
     /**
      * Session is disabled because there is no service for this user.
      *
      * @hide
      */
-    public static final int STATE_DISABLED_NO_SERVICE = 3;
+    public static final int STATE_DISABLED = 0x4;
 
     /**
      * Session is disabled because its id already existed on server.
      *
      * @hide
      */
-    public static final int STATE_DISABLED_DUPLICATED_ID = 4;
+    public static final int STATE_DUPLICATED_ID = 0x8;
+
+    /**
+     * Session is disabled because service is not set for user.
+     *
+     * @hide
+     */
+    public static final int STATE_NO_SERVICE = 0x10;
 
     /**
      * Session is disabled by FLAG_SECURE
      *
      * @hide
      */
-    public static final int STATE_DISABLED_BY_FLAG_SECURE = 5;
+    public static final int STATE_FLAG_SECURE = 0x20;
+
+    /**
+     * Session is disabled manually by the specific app.
+     *
+     * @hide
+     */
+    public static final int STATE_BY_APP = 0x40;
+
+    /**
+     * Session is disabled because session start was never replied.
+     *
+     * @hide
+     */
+    public static final int STATE_NO_RESPONSE = 0x80;
+
+    /**
+     * Session is disabled because an internal error.
+     *
+     * @hide
+     */
+    public static final int STATE_INTERNAL_ERROR = 0x100;
 
     private static final int INITIAL_CHILDREN_CAPACITY = 5;
 
+    /** @hide */
+    public static final int FLUSH_REASON_FULL = 1;
+    /** @hide */
+    public static final int FLUSH_REASON_ACTIVITY_PAUSED = 2;
+    /** @hide */
+    public static final int FLUSH_REASON_ACTIVITY_RESUMED = 3;
+    /** @hide */
+    public static final int FLUSH_REASON_SESSION_STARTED = 4;
+    /** @hide */
+    public static final int FLUSH_REASON_SESSION_FINISHED = 5;
+    /** @hide */
+    public static final int FLUSH_REASON_IDLE_TIMEOUT = 6;
+
+    /** @hide */
+    @IntDef(prefix = { "FLUSH_REASON_" }, value = {
+            FLUSH_REASON_FULL,
+            FLUSH_REASON_ACTIVITY_PAUSED,
+            FLUSH_REASON_ACTIVITY_RESUMED,
+            FLUSH_REASON_SESSION_STARTED,
+            FLUSH_REASON_SESSION_FINISHED,
+            FLUSH_REASON_IDLE_TIMEOUT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface FlushReason{}
+
+
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     private final Object mLock = new Object();
@@ -110,7 +169,7 @@
     @Nullable
     protected final String mId;
 
-    private int mState = STATE_UNKNOWN;
+    private int mState = UNKNWON_STATE;
 
     // Lazily created on demand.
     private ContentCaptureSessionId mContentCaptureSessionId;
@@ -182,7 +241,7 @@
     /**
      * Flushes the buffered events to the service.
      */
-    abstract void flush();
+    abstract void flush(@FlushReason int reason);
 
     /**
      * Destroys this session, flushing out all pending notifications to the service.
@@ -220,7 +279,7 @@
         }
 
         try {
-            flush();
+            flush(FLUSH_REASON_SESSION_FINISHED);
         } finally {
             onDestroy();
         }
@@ -377,26 +436,31 @@
         return mId;
     }
 
-    /**
-     * @hide
-     */
+    /** @hide */
     @NonNull
     protected static String getStateAsString(int state) {
-        switch (state) {
-            case STATE_UNKNOWN:
-                return "UNKNOWN";
-            case STATE_WAITING_FOR_SERVER:
-                return "WAITING_FOR_SERVER";
-            case STATE_ACTIVE:
-                return "ACTIVE";
-            case STATE_DISABLED_NO_SERVICE:
-                return "DISABLED_NO_SERVICE";
-            case STATE_DISABLED_DUPLICATED_ID:
-                return "DISABLED_DUPLICATED_ID";
-            case STATE_DISABLED_BY_FLAG_SECURE:
-                return "DISABLED_FLAG_SECURE";
+        return state + " (" + (state == UNKNWON_STATE ? "UNKNOWN"
+                : DebugUtils.flagsToString(ContentCaptureSession.class, "STATE_", state)) + ")";
+    }
+
+    /** @hide */
+    @NonNull
+    static String getflushReasonAsString(@FlushReason int reason) {
+        switch (reason) {
+            case FLUSH_REASON_FULL:
+                return "FULL";
+            case FLUSH_REASON_ACTIVITY_PAUSED:
+                return "PAUSED";
+            case FLUSH_REASON_ACTIVITY_RESUMED:
+                return "RESUMED";
+            case FLUSH_REASON_SESSION_STARTED:
+                return "STARTED";
+            case FLUSH_REASON_SESSION_FINISHED:
+                return "FINISHED";
+            case FLUSH_REASON_IDLE_TIMEOUT:
+                return "IDLE";
             default:
-                return "INVALID:" + state;
+                return "UNKOWN-" + reason;
         }
     }
 }
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index a29aaf0..f0778fa 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -35,7 +35,7 @@
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
-import android.os.SystemClock;
+import android.util.LocalLog;
 import android.util.Log;
 import android.util.TimeUtils;
 import android.view.autofill.AutofillId;
@@ -88,6 +88,7 @@
      */
     public static final String EXTRA_BINDER = "binder";
 
+    // TODO(b/111276913): make sure disabled state is in sync with manager's disabled
     @NonNull
     private final AtomicBoolean mDisabled;
 
@@ -113,7 +114,7 @@
     @Nullable
     private DeathRecipient mDirectServiceVulture;
 
-    private int mState = STATE_UNKNOWN;
+    private int mState = UNKNWON_STATE;
 
     @Nullable
     private IBinder mApplicationToken;
@@ -130,14 +131,17 @@
     // Used just for debugging purposes (on dump)
     private long mNextFlush;
 
+    // TODO(b/121044064): use settings to set size
+    private final LocalLog mFlushHistory = new LocalLog(10);
+
     /** @hide */
     protected MainContentCaptureSession(@NonNull Context context, @NonNull Handler handler,
             @Nullable IContentCaptureManager systemServerInterface,
-            @NonNull AtomicBoolean disabled) {
+            @NonNull boolean disabled) {
         mContext = context;
         mHandler = handler;
         mSystemServerInterface = systemServerInterface;
-        mDisabled = disabled;
+        mDisabled = new AtomicBoolean(disabled);
     }
 
     @Override
@@ -171,8 +175,9 @@
     }
 
     @Override
-    void flush() {
-        mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleForceFlush, this));
+    void flush(@FlushReason int reason) {
+        mHandler.sendMessage(
+                obtainMessage(MainContentCaptureSession::handleForceFlush, this, reason));
     }
 
     @Override
@@ -184,10 +189,13 @@
 
     private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName,
             int flags) {
-        if (mState != STATE_UNKNOWN) {
-            // TODO(b/111276913): revisit this scenario
-            Log.w(TAG, "ignoring handleStartSession(" + token + ") while on state "
-                    + getStateAsString(mState));
+        if (handleHasStarted()) {
+            // TODO(b/122959591): make sure this is expected (and when), or use Log.w
+            if (DEBUG) {
+                Log.d(TAG, "ignoring handleStartSession(" + token + "/"
+                        + ComponentName.flattenToShortString(componentName) + " while on state "
+                        + getStateAsString(mState));
+            }
             return;
         }
         mState = STATE_WAITING_FOR_SERVER;
@@ -196,7 +204,7 @@
 
         if (VERBOSE) {
             Log.v(TAG, "handleStartSession(): token=" + token + ", act="
-                    + getActivityDebugName() + ", id=" + mId);
+                    + getDebugState() + ", id=" + mId);
         }
 
         try {
@@ -211,7 +219,7 @@
                                 binder = resultData.getBinder(EXTRA_BINDER);
                                 if (binder == null) {
                                     Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result");
-                                    handleResetState();
+                                    handleResetSession(STATE_DISABLED | STATE_INTERNAL_ERROR);
                                     return;
                                 }
                             }
@@ -233,7 +241,6 @@
      * @param binder handle to {@code IContentCaptureDirectManager}
      */
     private void handleSessionStarted(int resultCode, @Nullable IBinder binder) {
-        mState = resultCode;
         if (binder != null) {
             mDirectServiceInterface = IContentCaptureDirectManager.Stub.asInterface(binder);
             mDirectServiceVulture = () -> {
@@ -247,31 +254,39 @@
             }
         }
 
-        // TODO(b/111276913): change the resultCode to use flags so there's just one flag for
-        // disabled stuff
-        if (resultCode == STATE_DISABLED_NO_SERVICE || resultCode == STATE_DISABLED_DUPLICATED_ID
-                || resultCode == STATE_DISABLED_BY_FLAG_SECURE) {
-            mDisabled.set(true);
-            handleResetSession(/* resetState= */ false);
+        if ((resultCode & STATE_DISABLED) != 0) {
+            handleResetSession(resultCode);
         } else {
+            mState = resultCode;
             mDisabled.set(false);
         }
         if (VERBOSE) {
-            Log.v(TAG, "handleSessionStarted() result: code=" + resultCode + ", id=" + mId
+            Log.v(TAG, "handleSessionStarted() result: id=" + mId + " resultCode=" + resultCode
                     + ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get()
                     + ", binder=" + binder + ", events=" + (mEvents == null ? 0 : mEvents.size()));
         }
     }
 
     private void handleSendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
+        final int eventType = event.getType();
+        if (!handleHasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) {
+            // TODO(b/120494182): comment when this could happen (dialogs?)
+            Log.v(TAG, "handleSendEvent(" + getDebugState() + ", "
+                    + ContentCaptureEvent.getTypeAsString(eventType)
+                    + "): session not started yet");
+            return;
+        }
+        if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
         if (mEvents == null) {
             if (VERBOSE) {
-                Log.v(TAG, "Creating buffer for " + MAX_BUFFER_SIZE + " events");
+                Log.v(TAG, "handleSendEvent(" + getDebugState() + ", "
+                        + ContentCaptureEvent.getTypeAsString(eventType)
+                        + "): creating buffer for " + MAX_BUFFER_SIZE + " events");
             }
             mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
         }
 
-        if (!mEvents.isEmpty() && event.getType() == TYPE_VIEW_TEXT_CHANGED) {
+        if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) {
             final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
 
             // TODO(b/121045053): check if flags match
@@ -294,76 +309,104 @@
         final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE;
 
         if (bufferEvent && !forceFlush) {
-            handleScheduleFlush(/* checkExisting= */ true);
+            handleScheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
             return;
         }
 
         if (mState != STATE_ACTIVE && numberEvents >= MAX_BUFFER_SIZE) {
             // Callback from startSession hasn't been called yet - typically happens on system
             // apps that are started before the system service
-            // TODO(b/111276913): try to ignore session while system is not ready / boot
+            // TODO(b/122959591): try to ignore session while system is not ready / boot
             // not complete instead. Similarly, the manager service should return right away
             // when the user does not have a service set
             if (DEBUG) {
-                Log.d(TAG, "Closing session for " + getActivityDebugName()
-                        + " after " + numberEvents + " delayed events and state "
-                        + getStateAsString(mState));
+                Log.d(TAG, "Closing session for " + getDebugState()
+                        + " after " + numberEvents + " delayed events");
             }
-            handleResetState();
+            handleResetSession(STATE_DISABLED | STATE_NO_RESPONSE);
             // TODO(b/111276913): blacklist activity / use special flag to indicate that
             // when it's launched again
             return;
         }
+        final int flushReason;
+        switch (eventType) {
+            case ContentCaptureEvent.TYPE_SESSION_STARTED:
+                flushReason = FLUSH_REASON_SESSION_STARTED;
+                break;
+            case ContentCaptureEvent.TYPE_SESSION_FINISHED:
+                flushReason = FLUSH_REASON_SESSION_FINISHED;
+                break;
+            default:
+                flushReason = FLUSH_REASON_FULL;
+        }
 
-        handleForceFlush();
+        handleForceFlush(flushReason);
     }
 
-    private void handleScheduleFlush(boolean checkExisting) {
+    private boolean handleHasStarted() {
+        return mState != UNKNWON_STATE;
+    }
+
+    private void handleScheduleFlush(@FlushReason int reason, boolean checkExisting) {
+        if (!handleHasStarted()) {
+            Log.v(TAG, "handleScheduleFlush(" + getDebugState() + "): session not started yet");
+            return;
+        }
         if (checkExisting && mHandler.hasMessages(MSG_FLUSH)) {
             // "Renew" the flush message by removing the previous one
             mHandler.removeMessages(MSG_FLUSH);
         }
-        mNextFlush = SystemClock.elapsedRealtime() + FLUSHING_FREQUENCY_MS;
+        mNextFlush = System.currentTimeMillis() + FLUSHING_FREQUENCY_MS;
         if (VERBOSE) {
-            Log.v(TAG, "Scheduled to flush in " + FLUSHING_FREQUENCY_MS + "ms: " + mNextFlush);
+            Log.v(TAG, "handleScheduleFlush(" + getDebugState()
+                    + ", reason=" + getflushReasonAsString(reason) + "): scheduled to flush in "
+                    + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
         }
         mHandler.sendMessageDelayed(
-                obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this)
+                obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this, reason)
                 .setWhat(MSG_FLUSH), FLUSHING_FREQUENCY_MS);
     }
 
-    private void handleFlushIfNeeded() {
+    private void handleFlushIfNeeded(@FlushReason int reason) {
         if (mEvents.isEmpty()) {
             if (VERBOSE) Log.v(TAG, "Nothing to flush");
             return;
         }
-        handleForceFlush();
+        handleForceFlush(reason);
     }
 
-    private void handleForceFlush() {
+    private void handleForceFlush(@FlushReason int reason) {
         if (mEvents == null) return;
 
         if (mDirectServiceInterface == null) {
             if (VERBOSE) {
-                Log.v(TAG, "handleForceFlush(): hold your horses, client not ready: " + mEvents);
+                Log.v(TAG, "handleForceFlush(" + getDebugState()
+                        + ", reason=" + getflushReasonAsString(reason)
+                        + "): hold your horses, client not ready: " + mEvents);
             }
             if (!mHandler.hasMessages(MSG_FLUSH)) {
-                handleScheduleFlush(/* checkExisting= */ false);
+                handleScheduleFlush(reason, /* checkExisting= */ false);
             }
             return;
         }
 
         final int numberEvents = mEvents.size();
+        final String reasonString = getflushReasonAsString(reason);
+        if (DEBUG) {
+            Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState()
+                    + ". Reason: " + reasonString);
+        }
+        // Logs reason, size, max size, idle timeout
+        final String logRecord = "r=" + reasonString + " s=" + numberEvents
+                + " m=" + MAX_BUFFER_SIZE + " i=" + FLUSHING_FREQUENCY_MS;
         try {
-            if (DEBUG) {
-                Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getActivityDebugName());
-            }
+            mFlushHistory.log(logRecord);
             mHandler.removeMessages(MSG_FLUSH);
 
             final ParceledListSlice<ContentCaptureEvent> events = handleClearEvents();
             mDirectServiceInterface.sendEvents(events);
         } catch (RemoteException e) {
-            Log.w(TAG, "Error sending " + numberEvents + " for " + getActivityDebugName()
+            Log.w(TAG, "Error sending " + numberEvents + " for " + getDebugState()
                     + ": " + e);
         }
     }
@@ -386,7 +429,7 @@
         if (DEBUG) {
             Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with "
                     + (mEvents == null ? 0 : mEvents.size()) + " event(s) for "
-                    + getActivityDebugName());
+                    + getDebugState());
         }
 
         try {
@@ -395,21 +438,19 @@
             mSystemServerInterface.finishSession(mContext.getUserId(), mId);
         } catch (RemoteException e) {
             Log.e(TAG, "Error destroying system-service session " + mId + " for "
-                    + getActivityDebugName() + ": " + e);
+                    + getDebugState() + ": " + e);
         }
     }
 
-    private void handleResetState() {
-        handleResetSession(/* resetState= */ true);
-    }
-
     // TODO(b/122454205): once we support multiple sessions, we might need to move some of these
     // clearings out.
-    private void handleResetSession(boolean resetState) {
-        if (resetState) {
-            mState = STATE_UNKNOWN;
+    private void handleResetSession(int newState) {
+        if (VERBOSE) {
+            Log.v(TAG, "handleResetSession(" + getActivityName() + "): from "
+                    + getStateAsString(mState) + " to " + getStateAsString(newState));
         }
-
+        mState = newState;
+        mDisabled.set((newState & STATE_DISABLED) != 0);
         // TODO(b/122454205): must reset children (which currently is owned by superclass)
         mApplicationToken = null;
         mComponentName = null;
@@ -483,7 +524,6 @@
 
     @Override
     void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
-        pw.print(prefix); pw.print("id: "); pw.println(mId);
         pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
         pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId());
         if (mSystemServerInterface != null) {
@@ -496,8 +536,7 @@
         }
         pw.print(prefix); pw.print("mDisabled: "); pw.println(mDisabled.get());
         pw.print(prefix); pw.print("isEnabled(): "); pw.println(isContentCaptureEnabled());
-        pw.print(prefix); pw.print("state: "); pw.print(mState); pw.print(" (");
-        pw.print(getStateAsString(mState)); pw.println(")");
+        pw.print(prefix); pw.print("state: "); pw.println(getStateAsString(mState));
         if (mApplicationToken != null) {
             pw.print(prefix); pw.print("app token: "); pw.println(mApplicationToken);
         }
@@ -519,16 +558,25 @@
             }
             pw.print(prefix); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS);
             pw.print(prefix); pw.print("next flush: ");
-            TimeUtils.formatDuration(mNextFlush - SystemClock.elapsedRealtime(), pw); pw.println();
+            TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
+            pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
         }
+        pw.print(prefix); pw.println("flush history:");
+        mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+
         super.dump(prefix, pw);
     }
 
     /**
      * Gets a string that can be used to identify the activity on logging statements.
      */
-    private String getActivityDebugName() {
-        return mComponentName == null ? mContext.getPackageName()
-                : mComponentName.flattenToShortString();
+    private String getActivityName() {
+        return mComponentName == null
+                ? "pkg:" + mContext.getPackageName()
+                : "act:" + mComponentName.flattenToShortString();
+    }
+
+    private String getDebugState() {
+        return getActivityName() + " (state=" + getStateAsString(mState) + ")";
     }
 }
diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java
index 5b957156..e2a763e 100644
--- a/core/java/android/view/inspector/InspectableProperty.java
+++ b/core/java/android/view/inspector/InspectableProperty.java
@@ -105,7 +105,6 @@
     /**
      * One entry in an enumeration packed into a primitive {int}.
      *
-     * @see IntEnumMapping
      * @hide
      */
     @Target({TYPE})
diff --git a/core/java/android/view/inspector/IntEnumMapping.java b/core/java/android/view/inspector/IntEnumMapping.java
deleted file mode 100644
index 69f6dce..0000000
--- a/core/java/android/view/inspector/IntEnumMapping.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.view.inspector;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.util.ArrayList;
-
-/**
- * Maps the values of an {int} property to string names for properties that encode enumerations.
- *
- * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper}
- * for enumerations packed into primitive {int} properties.
- *
- * This class is immutable, and must be constructed by a {@link Builder}.
- *
- * @see PropertyMapper#mapIntEnum(String, int, IntEnumMapping)
- */
-public final class IntEnumMapping {
-    private final Value[] mValues;
-
-    /**
-     * Map from a property value to a string name.
-     *
-     * @param value The value of a property
-     * @return The name of the enumeration value, null if the value is not mapped
-     */
-    @Nullable
-    public String nameOf(int value) {
-        for (Value valueTuple : mValues) {
-            if (valueTuple.mValue == value) {
-                return valueTuple.mName;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Create a new instance from a builder.
-     *
-     * This constructor is private, use {@link Builder#build()} instead.
-     *
-     * @param builder A builder to create from
-     */
-    private IntEnumMapping(Builder builder) {
-        mValues = builder.mValues.toArray(new Value[builder.mValues.size()]);
-    }
-
-    /**
-     * A builder for {@link IntEnumMapping}
-     */
-    public static final class Builder {
-        private final ArrayList<Value> mValues;
-
-        public Builder() {
-            mValues = new ArrayList<>();
-        }
-
-        /**
-         * Add a new entry to this mapping.
-         *
-         * @param name Name of the enumeration value
-         * @param value Int value of the enumeration value
-         * @return This builder
-         */
-        @NonNull
-        public Builder addValue(@NonNull String name, int value) {
-            mValues.add(new Value(name, value));
-            return this;
-        }
-
-        /**
-         * Clear the builder, allowing for recycling.
-         */
-        public void clear() {
-            mValues.clear();
-        }
-
-        /**
-         * Build a new {@link IntEnumMapping} from this builder
-         *
-         * @return A new mapping
-         */
-        @NonNull
-        public IntEnumMapping build() {
-            return new IntEnumMapping(this);
-        }
-    }
-
-    /**
-     * Inner class that holds the name and value of an enumeration value.
-     */
-    private static final class Value {
-        @NonNull private final String mName;
-        private final int mValue;
-
-        private Value(@NonNull String name, int value) {
-            mName = name;
-            mValue = value;
-        }
-    }
-}
diff --git a/core/java/android/view/inspector/IntFlagMapping.java b/core/java/android/view/inspector/IntFlagMapping.java
index dcb87e1..8f7dfd5 100644
--- a/core/java/android/view/inspector/IntFlagMapping.java
+++ b/core/java/android/view/inspector/IntFlagMapping.java
@@ -19,14 +19,20 @@
 import android.annotation.NonNull;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
- * Maps the values of an {int} property to arrays of string for properties that encode flags.
+ * Maps the values of an {@code int} property to arrays of string for properties that encode flags.
  *
  * An {@link InspectionCompanion} may provide an instance of this class to a {@link PropertyMapper}
- * for flag values packed into primitive {int} properties.
+ * for flag values packed into primitive {@code int} properties.
  *
- * Each flag has a
+ * Each flag has a mask and a target value, for non-exclusive flags, the target can also be used as
+ * the mask. A given integer value is compared against each flag to find what flags are active for
+ * it by bitwise anding it with the mask and comparing the result against the target, that is,
+ * {@code (value & mask) == target}.
  *
  * This class is immutable, and must be constructed by a {@link Builder}.
  *
@@ -42,8 +48,8 @@
      * @return The names of the enabled flags
      */
     @NonNull
-    public String[] namesOf(int value) {
-        ArrayList<String> enabledFlagNames = new ArrayList<>(mFlags.length);
+    public Set<String> get(int value) {
+        final Set<String> enabledFlagNames = new HashSet<>(mFlags.length);
 
         for (Flag flag : mFlags) {
             if (flag.isEnabledFor(value)) {
@@ -51,7 +57,7 @@
             }
         }
 
-        return enabledFlagNames.toArray(new String[enabledFlagNames.size()]);
+        return Collections.unmodifiableSet(enabledFlagNames);
     }
 
     /**
@@ -81,7 +87,7 @@
          * The target value will be used as a mask, to handle the common case where flag values
          * are not mutually exclusive. The flag will be considered enabled for a property value if
          * the result of bitwise anding the target and the value equals the target, that is:
-         * {(value & target) == target}.
+         * {@code (value & target) == target}.
          *
          * @param name The name of the flag
          * @param target The value to compare against
@@ -97,7 +103,7 @@
          * Add a new flag with a mask.
          *
          * The flag will be considered enabled for a property value if the result of bitwise anding
-         * the value and the mask equals the target, that is: {(value & mask) == target}.
+         * the value and the mask equals the target, that is: {@code (value & mask) == target}.
          *
          * @param name The name of the flag
          * @param target The value to compare against
@@ -111,13 +117,6 @@
         }
 
         /**
-         * Clear the builder, allowing for recycling.
-         */
-        public void clear() {
-            mFlags.clear();
-        }
-
-        /**
          * Build a new {@link IntFlagMapping} from this builder.
          *
          * @return A new mapping
@@ -143,7 +142,7 @@
         }
 
         /**
-         * Compare the supplied property value against the mask and taget.
+         * Compare the supplied property value against the mask and target.
          *
          * @param value The value to check
          * @return True if this flag is enabled
diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java
index 5fb291b..e20582b 100644
--- a/core/java/android/view/inspector/PropertyMapper.java
+++ b/core/java/android/view/inspector/PropertyMapper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
+import android.util.SparseArray;
 
 /**
  * An interface for mapping the string names of inspectable properties to integer identifiers.
@@ -154,7 +155,7 @@
     int mapIntEnum(
             @NonNull String name,
             @AttrRes int attributeId,
-            @NonNull IntEnumMapping mapping);
+            @NonNull SparseArray<String> mapping);
 
     /**
      * Map a string name to an integer ID for a flag set packed into an int property.
diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java
index fd83e8d..a8b7ecc 100644
--- a/core/java/android/view/inspector/PropertyReader.java
+++ b/core/java/android/view/inspector/PropertyReader.java
@@ -25,7 +25,13 @@
 /**
  * An interface for reading the properties of an inspectable object.
  *
- * Used as the parameter for {@link InspectionCompanion#readProperties(Object, PropertyReader)}.
+ * {@code PropertyReader} is defined as an interface that will be called by
+ * {@link InspectionCompanion#readProperties(Object, PropertyReader)}. This approach allows a
+ * client inspector to read the values of primitive properties without the overhead of
+ * instantiating a class to hold the property values for each inspection pass. If an inspectable
+ * remains unchanged between reading passes, it should be possible for a {@code PropertyReader} to
+ * avoid new allocations for subsequent reading passes.
+ *
  * It has separate methods for all primitive types to avoid autoboxing overhead if a concrete
  * implementation is able to work with primitives. Implementations should be prepared to accept
  * {null} as the value of {@link PropertyReader#readObject(int, Object)}.
@@ -38,7 +44,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {boolean}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code boolean}
      */
     void readBoolean(int id, boolean value);
 
@@ -47,7 +53,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {byte}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code byte}
      */
     void readByte(int id, byte value);
 
@@ -56,7 +62,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {char}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code char}
      */
     void readChar(int id, char value);
 
@@ -65,7 +71,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {double}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code double}
      */
     void readDouble(int id, double value);
 
@@ -74,7 +80,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {float}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code float}
      */
     void readFloat(int id, float value);
 
@@ -83,7 +89,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as an {int}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as an {@code int}
      */
     void readInt(int id, int value);
 
@@ -92,7 +98,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {long}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code long}
      */
     void readLong(int id, long value);
 
@@ -101,7 +107,7 @@
      *
      * @param id Identifier of the property from a {@link PropertyMapper}
      * @param value Value of the property
-     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {short}
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {@code short}
      */
     void readShort(int id, short value);
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index bad2dbf..6039350 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -69,6 +70,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * A View that displays web pages.
@@ -1688,6 +1690,84 @@
         return mProvider.getWebViewClient();
     }
 
+
+    /**
+     * Gets the WebView renderer associated with this WebView.
+     *
+     * <p>In {@link android.os.Build.VERSION_CODES#O} and above, WebView may
+     * run in "multiprocess" mode. In multiprocess mode, rendering of web
+     * content is performed by a sandboxed renderer process separate to the
+     * application process.  This renderer process may be shared with other
+     * WebViews in the application, but is not shared with other application
+     * processes.
+     *
+     * <p>If WebView is running in multiprocess mode, this method returns a
+     * handle to the renderer process associated with the WebView, which can
+     * be used to control the renderer process.
+     *
+     * @return the {@link WebViewRenderer} renderer handle associated
+     *         with this {@link WebView}, or {@code null} if
+     *         WebView is not runing in multiprocess mode.
+     */
+    @Nullable
+    public WebViewRenderer getWebViewRenderer() {
+        checkThread();
+        return mProvider.getWebViewRenderer();
+    }
+
+    /**
+     * Sets the renderer client object associated with this WebView.
+     *
+     * <p>The renderer client encapsulates callbacks relevant to WebView renderer
+     * state. See {@link WebViewRendererClient} for details.
+     *
+     * <p>Although many WebView instances may share a single underlying
+     * renderer, and renderers may live either in the application
+     * process, or in a sandboxed process that is isolated from the
+     * application process, instances of {@link WebViewRendererClient}
+     * are set per-WebView.  Callbacks represent renderer events from
+     * the perspective of this WebView, and may or may not be correlated
+     * with renderer events affecting other WebViews.
+     *
+     * @param executor the Executor on which {@link WebViewRendererClient} callbacks will execute.
+     * @param webViewRendererClient the {@link WebViewRendererClient} object.
+     */
+    public void setWebViewRendererClient(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull WebViewRendererClient webViewRendererClient) {
+        checkThread();
+        mProvider.setWebViewRendererClient(executor, webViewRendererClient);
+    }
+
+    /**
+     * Sets the renderer client object associated with this WebView.
+     *
+     * See {@link #setWebViewRendererClient(Executor,WebViewRendererClient)} for details.
+     *
+     * <p> {@link WebViewRendererClient} callbacks will run on the thread that this WebView was
+     * initialized on.
+     *
+     * @param webViewRendererClient the {@link WebViewRendererClient} object.
+     */
+    public void setWebViewRendererClient(
+            @Nullable WebViewRendererClient webViewRendererClient) {
+        checkThread();
+        mProvider.setWebViewRendererClient(null, webViewRendererClient);
+    }
+
+    /**
+     * Gets the renderer client object associated with this WebView.
+     *
+     * @return the {@link WebViewRendererClient} object associated with this WebView, if one has
+     * been set via {@link #setWebViewRendererClient(WebViewRendererClient)} or {@code null}
+     * otherwise.
+     */
+    @Nullable
+    public WebViewRendererClient getWebViewRendererClient() {
+        checkThread();
+        return mProvider.getWebViewRendererClient();
+    }
+
     /**
      * Registers the interface to be used when content can not be handled by
      * the rendering engine, and should be downloaded instead. This will replace
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 95e7a986..baf5826 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -54,6 +54,7 @@
 import java.io.BufferedWriter;
 import java.io.File;
 import java.util.Map;
+import java.util.concurrent.Executor;
 
 /**
  * WebView backend provider interface: this interface is the abstract backend to a WebView
@@ -237,6 +238,14 @@
 
     public WebViewClient getWebViewClient();
 
+    public WebViewRenderer getWebViewRenderer();
+
+    public void setWebViewRendererClient(
+            @Nullable Executor executor,
+            @Nullable WebViewRendererClient client);
+
+    public WebViewRendererClient getWebViewRendererClient();
+
     public void setDownloadListener(DownloadListener listener);
 
     public void setWebChromeClient(WebChromeClient client);
diff --git a/core/java/android/webkit/WebViewRenderer.java b/core/java/android/webkit/WebViewRenderer.java
new file mode 100644
index 0000000..5328254
--- /dev/null
+++ b/core/java/android/webkit/WebViewRenderer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+/**
+ * WebViewRenderer provides an opaque handle to a {@link WebView} renderer.
+ */
+public abstract class WebViewRenderer {
+    /**
+     * Cause this renderer to terminate.
+     *
+     * <p>Calling this on a not yet started, or an already terminated renderer will have no effect.
+     *
+     * <p>Terminating a renderer process may have an effect on multiple {@link WebView} instances.
+     *
+     * <p>Renderer termination must be handled by properly overriding
+     * {@link WebViewClient#onRenderProcessGone} for every WebView that shares this
+     * renderer. If termination is not handled by all associated WebViews, then the application
+     * process will also be terminated.
+     *
+     * @return {@code true} if it was possible to terminate this renderer, {@code false} otherwise.
+     */
+    public abstract boolean terminate();
+
+    /**
+     * This class cannot be created by applications.
+     * @hide
+     */
+    public WebViewRenderer() {
+    }
+}
diff --git a/core/java/android/webkit/WebViewRendererClient.java b/core/java/android/webkit/WebViewRendererClient.java
new file mode 100644
index 0000000..2fadf54
--- /dev/null
+++ b/core/java/android/webkit/WebViewRendererClient.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * Used to receive callbacks on {@link WebView} renderer events.
+ *
+ * WebViewRendererClient instances may be set or retrieved via {@link
+ * WebView#setWebViewRendererClient(WebViewRendererClient)} and {@link
+ * WebView#getWebViewRendererClient()}.
+ *
+ * Instances may be attached to multiple WebViews, and thus a single renderer event may cause
+ * a callback to be called multiple times with different WebView parameters.
+ */
+public abstract class WebViewRendererClient {
+    /**
+     * Called when the renderer currently associated with {@code view} becomes unresponsive as a
+     * result of a long running blocking task such as the execution of JavaScript.
+     *
+     * <p>If a WebView fails to process an input event, or successfully navigate to a new URL within
+     * a reasonable time frame, the renderer is considered to be unresponsive, and this callback
+     * will be called.
+     *
+     * <p>This callback will continue to be called at regular intervals as long as the renderer
+     * remains unresponsive. If the renderer becomes responsive again, {@link
+     * WebViewRendererClient#onRendererResponsive} will be called once, and this method will not
+     * subsequently be called unless another period of unresponsiveness is detected.
+     *
+     * <p>No action is taken by WebView as a result of this method call. Applications may
+     * choose to terminate the associated renderer via the object that is passed to this callback,
+     * if in multiprocess mode, however this must be accompanied by correctly handling
+     * {@link WebViewClient#onRenderProcessGone} for this WebView, and all other WebViews associated
+     * with the same renderer. Failure to do so will result in application termination.
+     *
+     * @param view The {@link WebView} for which unresponsiveness was detected.
+     * @param renderer The {@link WebViewRenderer} that has become unresponsive,
+     * or {@code null} if WebView is running in single process mode.
+     */
+    public abstract void onRendererUnresponsive(
+            @NonNull WebView view, @Nullable WebViewRenderer renderer);
+
+    /**
+     * Called once when an unresponsive renderer currently associated with {@code view} becomes
+     * responsive.
+     *
+     * <p>After a WebView renderer becomes unresponsive, which is notified to the application by
+     * {@link WebViewRendererClient#onRendererUnresponsive}, it is possible for the blocking
+     * renderer task to complete, returning the renderer to a responsive state. In that case,
+     * this method is called once to indicate responsiveness.
+     *
+     * <p>No action is taken by WebView as a result of this method call.
+     *
+     * @param view The {@link WebView} for which responsiveness was detected.
+     *
+     * @param renderer The {@link WebViewRenderer} that has become responsive, or {@code null} if
+     * WebView is running in single process mode.
+     */
+    public abstract void onRendererResponsive(
+            @NonNull WebView view, @Nullable WebViewRenderer renderer);
+}
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 2995a8f..7a00a51 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -58,6 +58,15 @@
         return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
     }
 
+    public boolean tapGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_TAP_SCREEN_GESTURE, user)
+                && tapSensorAvailable();
+    }
+
+    public boolean tapSensorAvailable() {
+        return !TextUtils.isEmpty(tapSensorType());
+    }
+
     public boolean doubleTapGestureEnabled(int user) {
         return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user)
                 && doubleTapSensorAvailable();
@@ -86,6 +95,10 @@
         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
     }
 
+    public String tapSensorType() {
+        return mContext.getResources().getString(R.string.config_dozeTapSensorType);
+    }
+
     public String longPressSensorType() {
         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
     }
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 5945958..72c67d7 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -139,6 +139,14 @@
         return mDestroyed;
     }
 
+    /**
+     * Gets the name of the service.
+     */
+    @NonNull
+    public final ComponentName getComponentName() {
+        return mComponentName;
+    }
+
     private void handleOnConnectedStateChangedInternal(boolean connected) {
         if (connected) {
             handlePendingRequests();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5125f5c..17cc6af 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -337,6 +337,25 @@
 
     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
 
+    private final Runnable mDeferSetCharging = new Runnable() {
+        @Override
+        public void run() {
+            synchronized (BatteryStatsImpl.this) {
+                if (mOnBattery) {
+                    // if the device gets unplugged in the time between this runnable being
+                    // executed and the lock being taken, we don't want to set charging state
+                    return;
+                }
+                boolean changed = setChargingLocked(true);
+                if (changed) {
+                    final long uptime = mClocks.uptimeMillis();
+                    final long elapsedRealtime = mClocks.elapsedRealtime();
+                    addHistoryRecordLocked(elapsedRealtime, uptime);
+                }
+            }
+        }
+    };
+
     /**
      * This handler is running on {@link BackgroundThread}.
      */
@@ -12340,6 +12359,14 @@
     }
 
     boolean setChargingLocked(boolean charging) {
+        // if the device is no longer charging, remove the callback
+        // if the device is now charging, it means that this is either called
+        // 1. directly when level >= 90
+        // 2. or from within the runnable that we deferred
+        // For 1. if we have an existing callback, remove it, since we will immediatelly send a
+        // ACTION_CHARGING
+        // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
+        mHandler.removeCallbacks(mDeferSetCharging);
         if (mCharging != charging) {
             mCharging = charging;
             if (charging) {
@@ -12678,12 +12705,23 @@
                     // charging even if it happens to go down a level.
                     changed |= setChargingLocked(true);
                     mLastChargeStepLevel = level;
-                } if (!mCharging) {
+                }
+                if (!mCharging) {
                     if (mLastChargeStepLevel < level) {
-                        // We have not reporting that we are charging, but the level has now
-                        // gone up, so consider the state to be charging.
-                        changed |= setChargingLocked(true);
+                        // We have not reported that we are charging, but the level has gone up,
+                        // but we would like to not have tons of activity from charging-constraint
+                        // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it.
                         mLastChargeStepLevel = level;
+                        if (!mHandler.hasCallbacks(mDeferSetCharging)) {
+                            mHandler.postDelayed(
+                                    mDeferSetCharging,
+                                    mConstants.BATTERY_CHARGED_DELAY_MS);
+                        }
+                    } else if (mLastChargeStepLevel > level) {
+                        // if we had deferred a runnable due to charge level increasing, but then
+                        // later the charge level drops (could be due to thermal issues), we don't
+                        // want to trigger the deferred runnable, so remove it here
+                        mHandler.removeCallbacks(mDeferSetCharging);
                     }
                 } else {
                     if (mLastChargeStepLevel > level) {
@@ -13300,6 +13338,8 @@
                 = "battery_level_collection_delay_ms";
         public static final String KEY_MAX_HISTORY_FILES = "max_history_files";
         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
+        public static final String KEY_BATTERY_CHARGED_DELAY_MS =
+                "battery_charged_delay_ms";
 
         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
@@ -13312,6 +13352,7 @@
         private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/
         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
+        private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
 
         public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE;
         public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
@@ -13324,6 +13365,7 @@
                 = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS;
         public int MAX_HISTORY_FILES;
         public int MAX_HISTORY_BUFFER; /*Bytes*/
+        public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
 
         private ContentResolver mResolver;
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -13392,6 +13434,9 @@
                                 DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
                                 : DEFAULT_MAX_HISTORY_BUFFER_KB)
                         * 1024;
+                BATTERY_CHARGED_DELAY_MS = mParser.getInt(
+                        KEY_BATTERY_CHARGED_DELAY_MS,
+                        DEFAULT_BATTERY_CHARGED_DELAY_MS);
             }
         }
 
@@ -13449,6 +13494,8 @@
             pw.println(MAX_HISTORY_FILES);
             pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("=");
             pw.println(MAX_HISTORY_BUFFER/1024);
+            pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
+            pw.println(BATTERY_CHARGED_DELAY_MS);
         }
     }
 
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index e97c9bc..bc49771 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -557,6 +557,38 @@
         return result;
     }
 
+    // FIXME: Should this be FastNative?
+    static void setColorLong(JNIEnv* env, jobject clazz, jlong paintHandle, jobject jColorSpace,
+            jfloat r, jfloat g, jfloat b, jfloat a) {
+        sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace);
+        if (GraphicsJNI::hasException(env)) {
+            return;
+        }
+
+        SkColor4f color = SkColor4f{r, g, b, a};
+        reinterpret_cast<Paint*>(paintHandle)->setColor4f(color, cs.get());
+    }
+
+    static void setShadowLayerLong(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius,
+                                   jfloat dx, jfloat dy, jobject jColorSpace,
+                                   jfloat r, jfloat g, jfloat b, jfloat a) {
+        sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace);
+        if (GraphicsJNI::hasException(env)) {
+            return;
+        }
+
+        SkColor4f color = SkColor4f{r, g, b, a};
+
+        Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+        if (radius <= 0) {
+            paint->setLooper(nullptr);
+        }
+        else {
+            SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius);
+            paint->setLooper(SkBlurDrawLooper::Make(color, cs.get(), sigma, dx, dy));
+        }
+    }
+
     // ------------------ @FastNative ---------------------------
 
     static jint setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) {
@@ -1075,6 +1107,9 @@
     {"nGetRunAdvance", "(J[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
     {"nGetOffsetForAdvance", "(J[CIIIIZF)I",
             (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
+    {"nSetColor","(JLandroid/graphics/ColorSpace;FFFF)V", (void*) PaintGlue::setColorLong},
+    {"nSetShadowLayer", "(JFFFLandroid/graphics/ColorSpace;FFFF)V",
+            (void*)PaintGlue::setShadowLayerLong},
 
     // --------------- @FastNative ----------------------
 
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 49a24a3..b2d3651 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -281,15 +281,18 @@
     std::unique_ptr<NativeCode> code;
     bool needs_native_bridge = false;
 
+    char* nativeloader_error_msg = nullptr;
     void* handle = OpenNativeLibrary(env,
                                      sdkVersion,
                                      pathStr.c_str(),
                                      classLoader,
                                      libraryPath,
                                      &needs_native_bridge,
-                                     &g_error_msg);
+                                     &nativeloader_error_msg);
 
     if (handle == nullptr) {
+        g_error_msg = nativeloader_error_msg;
+        NativeLoaderFreeErrorMessage(nativeloader_error_msg);
         ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
               pathStr.c_str(),
               g_error_msg.c_str());
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 12a8343b4..67c3064 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -841,6 +841,43 @@
     return jStatus;
 }
 
+static int android_media_AudioRecord_set_microphone_direction(JNIEnv *env, jobject thiz,
+                                                              jint direction) {
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioRecord pointer for setMicrophoneDirection()");
+        return (jint)AUDIO_JAVA_ERROR;
+    }
+
+    jint jStatus = AUDIO_JAVA_SUCCESS;
+    status_t status =
+        lpRecorder->setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction));
+    if (status != NO_ERROR) {
+        jStatus = nativeToJavaStatus(status);
+    }
+
+    return jStatus;
+}
+
+static int android_media_AudioRecord_set_microphone_field_dimension(JNIEnv *env, jobject thiz,
+                                                                    jfloat zoom) {
+    sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
+    if (lpRecorder == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioRecord pointer for setMicrophoneFieldDimension()");
+        return (jint)AUDIO_JAVA_ERROR;
+    }
+
+    jint jStatus = AUDIO_JAVA_SUCCESS;
+    status_t status = lpRecorder->setMicrophoneFieldDimension(zoom);
+    if (status != NO_ERROR) {
+        jStatus = nativeToJavaStatus(status);
+    }
+
+    return jStatus;
+}
+
 // ----------------------------------------------------------------------------
 static jint android_media_AudioRecord_get_port_id(JNIEnv *env,  jobject thiz) {
     sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
@@ -896,6 +933,10 @@
     {"native_get_active_microphones", "(Ljava/util/ArrayList;)I",
                                         (void *)android_media_AudioRecord_get_active_microphones},
     {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id},
+    {"native_set_microphone_direction", "(I)I",
+                                (void *)android_media_AudioRecord_set_microphone_direction},
+    {"native_set_microphone_field_dimension", "(F)I",
+                                (void *)android_media_AudioRecord_set_microphone_field_dimension},
 };
 
 // field names found in android/media/AudioRecord.java
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 10da892..aa10a2f 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -138,6 +138,7 @@
                 event->getDeviceId(), event->getSource(), event->getDisplayId(),
                 event->getAction(), event->getActionButton(), event->getFlags(),
                 event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
+                event->getClassification(),
                 event->getXOffset(), event->getYOffset(),
                 event->getXPrecision(), event->getYPrecision(),
                 event->getDownTime(), event->getHistoricalEventTime(i),
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 9ce6df1..ac13025 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -660,6 +660,10 @@
     if (t.duration() > 100ms) ALOGD("Excessive delay in setPowerMode()");
 }
 
+static jboolean nativeGetProtectedContentSupport(JNIEnv* env, jclass) {
+    return static_cast<jboolean>(SurfaceComposerClient::getProtectedContentSupport());
+}
+
 static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     status_t err = ctrl->clearLayerFrameStats();
@@ -1028,6 +1032,8 @@
             (void*)nativeGetAnimationFrameStats },
     {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
             (void*)nativeSetDisplayPowerMode },
+    {"nativeGetProtectedContentSupport", "()Z",
+            (void*)nativeGetProtectedContentSupport },
     {"nativeDeferTransactionUntil", "(JJLandroid/os/IBinder;J)V",
             (void*)nativeDeferTransactionUntil },
     {"nativeDeferTransactionUntilSurface", "(JJJJ)V",
diff --git a/core/proto/Android.bp b/core/proto/Android.bp
new file mode 100644
index 0000000..80cc2d4
--- /dev/null
+++ b/core/proto/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+// C++ library for Bluetooth platform wide protobuf definitions
+cc_library_static {
+    name: "libbt-platform-protos-lite",
+    host_supported: true,
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: [
+        "android/bluetooth/enums.proto",
+        "android/bluetooth/hci/enums.proto",
+    ],
+}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 49ca378..2148273 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -97,4 +97,7 @@
 
     // OPEN: Settings > System > Input & Gesture > Silence alerts
     SETTINGS_GESTURE_SILENCE = 1625;
+
+    // OPEN: Settings > System > Input & Gesture > Tap to check
+    SETTINGS_GESTURE_TAP_SCREEN = 1626;
 }
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
index d0c9226..76c240e 100644
--- a/core/proto/android/bluetooth/enums.proto
+++ b/core/proto/android/bluetooth/enums.proto
@@ -41,3 +41,18 @@
     ENABLE_DISABLE_REASON_USER_SWITCH = 8;
     ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9;
 }
+
+enum DirectionEnum {
+    DIRECTION_UNKNOWN = 0;
+    DIRECTION_OUTGOING = 1;
+    DIRECTION_INCOMING = 2;
+}
+
+// First item is the default value, other values follow Bluetooth spec definition
+enum LinkTypeEnum {
+    // Link type is at most 1 byte (0xFF), thus 0xFFF must not be a valid value
+    LINK_TYPE_UNKNOWN = 0xFFF;
+    LINK_TYPE_SCO = 0x00;
+    LINK_TYPE_ACL = 0x01;
+    LINK_TYPE_ESCO = 0x02;
+}
diff --git a/core/proto/android/bluetooth/hci/enums.proto b/core/proto/android/bluetooth/hci/enums.proto
new file mode 100644
index 0000000..e1d96bb
--- /dev/null
+++ b/core/proto/android/bluetooth/hci/enums.proto
@@ -0,0 +1,519 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package android.bluetooth.hci;
+
+option java_outer_classname = "BluetoothHciProtoEnums";
+option java_multiple_files = true;
+
+// HCI command opcodes (OCF+OGF) from Bluetooth 5.0 specification Vol 2, Part E, Section 7
+// Original definition: system/bt/stack/include/hcidefs.h
+enum CommandEnum {
+    // Opcode is at most 2 bytes (0xFFFF), thus 0xFFFFF must not be a valid value
+    CMD_UNKNOWN = 0xFFFFF;
+    // Link control commands 0x0400
+    CMD_INQUIRY = 0x0401;
+    CMD_INQUIRY_CANCEL = 0x0402;
+    CMD_PERIODIC_INQUIRY_MODE = 0x0403;
+    CMD_EXIT_PERIODIC_INQUIRY_MODE = 0x0404;
+    CMD_CREATE_CONNECTION = 0x0405;
+    CMD_DISCONNECT = 0x0406;
+    CMD_ADD_SCO_CONNECTION = 0x0407; // Deprecated since Bluetooth 1.2
+    CMD_CREATE_CONNECTION_CANCEL = 0x0408;
+    CMD_ACCEPT_CONNECTION_REQUEST = 0x0409;
+    CMD_REJECT_CONNECTION_REQUEST = 0x040A;
+    CMD_LINK_KEY_REQUEST_REPLY = 0x040B;
+    CMD_LINK_KEY_REQUEST_NEG_REPLY = 0x040C;
+    CMD_PIN_CODE_REQUEST_REPLY = 0x040D;
+    CMD_PIN_CODE_REQUEST_NEG_REPLY = 0x040E;
+    CMD_CHANGE_CONN_PACKET_TYPE = 0x040F;
+    CMD_AUTHENTICATION_REQUESTED = 0x0411;
+    CMD_SET_CONN_ENCRYPTION = 0x0413;
+    CMD_CHANGE_CONN_LINK_KEY = 0x0415;
+    CMD_MASTER_LINK_KEY = 0x0417;
+    CMD_RMT_NAME_REQUEST = 0x0419;
+    CMD_RMT_NAME_REQUEST_CANCEL = 0x041A;
+    CMD_READ_RMT_FEATURES = 0x041B;
+    CMD_READ_RMT_EXT_FEATURES = 0x041C;
+    CMD_READ_RMT_VERSION_INFO = 0x041D;
+    CMD_READ_RMT_CLOCK_OFFSET = 0x041F;
+    CMD_READ_LMP_HANDLE = 0x0420;
+    CMD_SETUP_ESCO_CONNECTION = 0x0428;
+    CMD_ACCEPT_ESCO_CONNECTION = 0x0429;
+    CMD_REJECT_ESCO_CONNECTION = 0x042A;
+    CMD_IO_CAPABILITY_REQUEST_REPLY = 0x042B;
+    CMD_USER_CONF_REQUEST_REPLY = 0x042C;
+    CMD_USER_CONF_VALUE_NEG_REPLY = 0x042D;
+    CMD_USER_PASSKEY_REQ_REPLY = 0x042E;
+    CMD_USER_PASSKEY_REQ_NEG_REPLY = 0x042F;
+    CMD_REM_OOB_DATA_REQ_REPLY = 0x0430;
+    CMD_REM_OOB_DATA_REQ_NEG_REPLY = 0x0433;
+    CMD_IO_CAP_REQ_NEG_REPLY = 0x0434;
+    // BEGIN: AMP commands (not used in system/bt)
+    CMD_CREATE_PHYSICAL_LINK = 0x0435;
+    CMD_ACCEPT_PHYSICAL_LINK = 0x0436;
+    CMD_DISCONNECT_PHYSICAL_LINK = 0x0437;
+    CMD_CREATE_LOGICAL_LINK = 0x0438;
+    CMD_ACCEPT_LOGICAL_LINK = 0x0439;
+    CMD_DISCONNECT_LOGICAL_LINK = 0x043A;
+    CMD_LOGICAL_LINK_CANCEL = 0x043B;
+    CMD_FLOW_SPEC_MODIFY = 0x043C;
+    // END: AMP commands
+    CMD_ENH_SETUP_ESCO_CONNECTION = 0x043D;
+    CMD_ENH_ACCEPT_ESCO_CONNECTION = 0x043E;
+    CMD_TRUNCATED_PAGE = 0x043F;
+    CMD_TRUNCATED_PAGE_CANCEL = 0x0440;
+    CMD_SET_CLB = 0x0441;
+    CMD_RECEIVE_CLB = 0x0442;
+    CMD_START_SYNC_TRAIN = 0x0443;
+    CMD_RECEIVE_SYNC_TRAIN = 0x0444;
+    CMD_REM_OOB_EXTENDED_DATA_REQ_REPLY = 0x0445; // Not currently used in system/bt
+    // Link policy commands 0x0800
+    CMD_HOLD_MODE = 0x0801;
+    CMD_SNIFF_MODE = 0x0803;
+    CMD_EXIT_SNIFF_MODE = 0x0804;
+    CMD_PARK_MODE = 0x0805;
+    CMD_EXIT_PARK_MODE = 0x0806;
+    CMD_QOS_SETUP = 0x0807;
+    CMD_ROLE_DISCOVERY = 0x0809;
+    CMD_SWITCH_ROLE = 0x080B;
+    CMD_READ_POLICY_SETTINGS = 0x080C;
+    CMD_WRITE_POLICY_SETTINGS = 0x080D;
+    CMD_READ_DEF_POLICY_SETTINGS = 0x080E;
+    CMD_WRITE_DEF_POLICY_SETTINGS = 0x080F;
+    CMD_FLOW_SPECIFICATION = 0x0810;
+    CMD_SNIFF_SUB_RATE = 0x0811;
+    // Host controller baseband commands 0x0C00
+    CMD_SET_EVENT_MASK = 0x0C01;
+    CMD_RESET = 0x0C03;
+    CMD_SET_EVENT_FILTER = 0x0C05;
+    CMD_FLUSH = 0x0C08;
+    CMD_READ_PIN_TYPE = 0x0C09;
+    CMD_WRITE_PIN_TYPE = 0x0C0A;
+    CMD_CREATE_NEW_UNIT_KEY = 0x0C0B;
+    CMD_GET_MWS_TRANS_LAYER_CFG = 0x0C0C; // Deprecated (not used in spec)
+    CMD_READ_STORED_LINK_KEY = 0x0C0D;
+    CMD_WRITE_STORED_LINK_KEY = 0x0C11;
+    CMD_DELETE_STORED_LINK_KEY = 0x0C12;
+    CMD_CHANGE_LOCAL_NAME = 0x0C13;
+    CMD_READ_LOCAL_NAME = 0x0C14;
+    CMD_READ_CONN_ACCEPT_TOUT = 0x0C15;
+    CMD_WRITE_CONN_ACCEPT_TOUT = 0x0C16;
+    CMD_READ_PAGE_TOUT = 0x0C17;
+    CMD_WRITE_PAGE_TOUT = 0x0C18;
+    CMD_READ_SCAN_ENABLE = 0x0C19;
+    CMD_WRITE_SCAN_ENABLE = 0x0C1A;
+    CMD_READ_PAGESCAN_CFG = 0x0C1B;
+    CMD_WRITE_PAGESCAN_CFG = 0x0C1C;
+    CMD_READ_INQUIRYSCAN_CFG = 0x0C1D;
+    CMD_WRITE_INQUIRYSCAN_CFG = 0x0C1E;
+    CMD_READ_AUTHENTICATION_ENABLE = 0x0C1F;
+    CMD_WRITE_AUTHENTICATION_ENABLE = 0x0C20;
+    CMD_READ_ENCRYPTION_MODE = 0x0C21; // Deprecated
+    CMD_WRITE_ENCRYPTION_MODE = 0x0C22; // Deprecated
+    CMD_READ_CLASS_OF_DEVICE = 0x0C23;
+    CMD_WRITE_CLASS_OF_DEVICE = 0x0C24;
+    CMD_READ_VOICE_SETTINGS = 0x0C25;
+    CMD_WRITE_VOICE_SETTINGS = 0x0C26;
+    CMD_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0C27;
+    CMD_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0C28;
+    CMD_READ_NUM_BCAST_REXMITS = 0x0C29;
+    CMD_WRITE_NUM_BCAST_REXMITS = 0x0C2A;
+    CMD_READ_HOLD_MODE_ACTIVITY = 0x0C2B;
+    CMD_WRITE_HOLD_MODE_ACTIVITY = 0x0C2C;
+    CMD_READ_TRANSMIT_POWER_LEVEL = 0x0C2D;
+    CMD_READ_SCO_FLOW_CTRL_ENABLE = 0x0C2E;
+    CMD_WRITE_SCO_FLOW_CTRL_ENABLE = 0x0C2F;
+    CMD_SET_HC_TO_HOST_FLOW_CTRL = 0x0C31;
+    CMD_HOST_BUFFER_SIZE = 0x0C33;
+    CMD_HOST_NUM_PACKETS_DONE = 0x0C35;
+    CMD_READ_LINK_SUPER_TOUT = 0x0C36;
+    CMD_WRITE_LINK_SUPER_TOUT = 0x0C37;
+    CMD_READ_NUM_SUPPORTED_IAC = 0x0C38;
+    CMD_READ_CURRENT_IAC_LAP = 0x0C39;
+    CMD_WRITE_CURRENT_IAC_LAP = 0x0C3A;
+    CMD_READ_PAGESCAN_PERIOD_MODE = 0x0C3B; // Deprecated
+    CMD_WRITE_PAGESCAN_PERIOD_MODE = 0x0C3C; // Deprecated
+    CMD_READ_PAGESCAN_MODE = 0x0C3D; // Deprecated
+    CMD_WRITE_PAGESCAN_MODE = 0x0C3E; // Deprecated
+    CMD_SET_AFH_CHANNELS = 0x0C3F;
+    CMD_READ_INQSCAN_TYPE = 0x0C42;
+    CMD_WRITE_INQSCAN_TYPE = 0x0C43;
+    CMD_READ_INQUIRY_MODE = 0x0C44;
+    CMD_WRITE_INQUIRY_MODE = 0x0C45;
+    CMD_READ_PAGESCAN_TYPE = 0x0C46;
+    CMD_WRITE_PAGESCAN_TYPE = 0x0C47;
+    CMD_READ_AFH_ASSESSMENT_MODE = 0x0C48;
+    CMD_WRITE_AFH_ASSESSMENT_MODE = 0x0C49;
+    CMD_READ_EXT_INQ_RESPONSE = 0x0C51;
+    CMD_WRITE_EXT_INQ_RESPONSE = 0x0C52;
+    CMD_REFRESH_ENCRYPTION_KEY = 0x0C53;
+    CMD_READ_SIMPLE_PAIRING_MODE = 0x0C55;
+    CMD_WRITE_SIMPLE_PAIRING_MODE = 0x0C56;
+    CMD_READ_LOCAL_OOB_DATA = 0x0C57;
+    CMD_READ_INQ_TX_POWER_LEVEL = 0x0C58;
+    CMD_WRITE_INQ_TX_POWER_LEVEL = 0x0C59;
+    CMD_READ_ERRONEOUS_DATA_RPT = 0x0C5A;
+    CMD_WRITE_ERRONEOUS_DATA_RPT = 0x0C5B;
+    CMD_ENHANCED_FLUSH = 0x0C5F;
+    CMD_SEND_KEYPRESS_NOTIF = 0x0C60;
+    CMD_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C61;
+    CMD_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C62;
+    CMD_SET_EVENT_MASK_PAGE_2 = 0x0C63;
+    CMD_READ_LOCATION_DATA = 0x0C64;
+    CMD_WRITE_LOCATION_DATA = 0x0C65;
+    CMD_READ_FLOW_CONTROL_MODE = 0x0C66;
+    CMD_WRITE_FLOW_CONTROL_MODE = 0x0C67;
+    CMD_READ_ENHANCED_TX_PWR_LEVEL = 0x0C68; // Not currently used in system/bt
+    CMD_READ_BE_FLUSH_TOUT = 0x0C69;
+    CMD_WRITE_BE_FLUSH_TOUT = 0x0C6A;
+    CMD_SHORT_RANGE_MODE = 0x0C6B;
+    CMD_READ_BLE_HOST_SUPPORT = 0x0C6C;
+    CMD_WRITE_BLE_HOST_SUPPORT = 0x0C6D;
+    CMD_SET_MWS_CHANNEL_PARAMETERS = 0x0C6E;
+    CMD_SET_EXTERNAL_FRAME_CONFIGURATION = 0x0C6F;
+    CMD_SET_MWS_SIGNALING = 0x0C70;
+    CMD_SET_MWS_TRANSPORT_LAYER = 0x0C71;
+    CMD_SET_MWS_SCAN_FREQUENCY_TABLE = 0x0C72;
+    CMD_SET_MWS_PATTERN_CONFIGURATION = 0x0C73;
+    CMD_SET_RESERVED_LT_ADDR = 0x0C74;
+    CMD_DELETE_RESERVED_LT_ADDR = 0x0C75;
+    CMD_WRITE_CLB_DATA = 0x0C76;
+    CMD_READ_SYNC_TRAIN_PARAM = 0x0C77;
+    CMD_WRITE_SYNC_TRAIN_PARAM = 0x0C78;
+    CMD_READ_SECURE_CONNS_SUPPORT = 0x0C79;
+    CMD_WRITE_SECURE_CONNS_SUPPORT = 0x0C7A;
+    CMD_READ_AUTHED_PAYLOAD_TIMEOUT = 0x0C7B; // Not currently used in system/bt
+    CMD_WRITE_AUTHED_PAYLOAD_TIMEOUT = 0x0C7C; // Not currently used in system/bt
+    CMD_READ_LOCAL_OOB_EXTENDED_DATA = 0x0C7D; // Not currently used in system/bt
+    CMD_READ_EXTENDED_PAGE_TIMEOUT = 0x0C7E; // Not currently used in system/bt
+    CMD_WRITE_EXTENDED_PAGE_TIMEOUT = 0x0C7F; // Not currently used in system/bt
+    CMD_READ_EXTENDED_INQUIRY_LENGTH = 0x0C80; // Not currently used in system/bt
+    CMD_WRITE_EXTENDED_INQUIRY_LENGTH = 0x0C81; // Not currently used in system/bt
+    // Informational parameter commands 0x1000
+    CMD_READ_LOCAL_VERSION_INFO = 0x1001;
+    CMD_READ_LOCAL_SUPPORTED_CMDS = 0x1002;
+    CMD_READ_LOCAL_FEATURES = 0x1003;
+    CMD_READ_LOCAL_EXT_FEATURES = 0x1004;
+    CMD_READ_BUFFER_SIZE = 0x1005;
+    CMD_READ_COUNTRY_CODE = 0x1007; // Deprecated
+    CMD_READ_BD_ADDR = 0x1009;
+    CMD_READ_DATA_BLOCK_SIZE = 0x100A;
+    CMD_READ_LOCAL_SUPPORTED_CODECS = 0x100B;
+    // Status parameter commands 0x1400
+    CMD_READ_FAILED_CONTACT_COUNTER = 0x1401;
+    CMD_RESET_FAILED_CONTACT_COUNTER = 0x1402;
+    CMD_GET_LINK_QUALITY = 0x1403;
+    CMD_READ_RSSI = 0x1405;
+    CMD_READ_AFH_CH_MAP = 0x1406;
+    CMD_READ_CLOCK = 0x1407;
+    CMD_READ_ENCR_KEY_SIZE = 0x1408;
+    CMD_READ_LOCAL_AMP_INFO = 0x1409;
+    CMD_READ_LOCAL_AMP_ASSOC = 0x140A;
+    CMD_WRITE_REMOTE_AMP_ASSOC = 0x140B;
+    CMD_GET_MWS_TRANSPORT_CFG = 0x140C; // Not currently used in system/bt
+    CMD_SET_TRIGGERED_CLK_CAPTURE = 0x140D; // Not currently used in system/bt
+    // Testing commands 0x1800
+    CMD_READ_LOOPBACK_MODE = 0x1801;
+    CMD_WRITE_LOOPBACK_MODE = 0x1802;
+    CMD_ENABLE_DEV_UNDER_TEST_MODE = 0x1803;
+    CMD_WRITE_SIMP_PAIR_DEBUG_MODE = 0x1804;
+    CMD_ENABLE_AMP_RCVR_REPORTS = 0x1807;
+    CMD_AMP_TEST_END = 0x1808;
+    CMD_AMP_TEST = 0x1809;
+    CMD_WRITE_SECURE_CONN_TEST_MODE = 0x180A; // Not currently used in system/bt
+    // BLE commands 0x2000
+    CMD_BLE_SET_EVENT_MASK = 0x2001;
+    CMD_BLE_READ_BUFFER_SIZE = 0x2002;
+    CMD_BLE_READ_LOCAL_SPT_FEAT = 0x2003;
+    CMD_BLE_WRITE_LOCAL_SPT_FEAT = 0x2004;
+    CMD_BLE_WRITE_RANDOM_ADDR = 0x2005;
+    CMD_BLE_WRITE_ADV_PARAMS = 0x2006;
+    CMD_BLE_READ_ADV_CHNL_TX_POWER = 0x2007;
+    CMD_BLE_WRITE_ADV_DATA = 0x2008;
+    CMD_BLE_WRITE_SCAN_RSP_DATA = 0x2009;
+    CMD_BLE_WRITE_ADV_ENABLE = 0x200A;
+    CMD_BLE_WRITE_SCAN_PARAMS = 0x200B;
+    CMD_BLE_WRITE_SCAN_ENABLE = 0x200C;
+    CMD_BLE_CREATE_LL_CONN = 0x200D;
+    CMD_BLE_CREATE_CONN_CANCEL = 0x200E;
+    CMD_BLE_READ_WHITE_LIST_SIZE = 0x200F;
+    CMD_BLE_CLEAR_WHITE_LIST = 0x2010;
+    CMD_BLE_ADD_WHITE_LIST = 0x2011;
+    CMD_BLE_REMOVE_WHITE_LIST = 0x2012;
+    CMD_BLE_UPD_LL_CONN_PARAMS = 0x2013;
+    CMD_BLE_SET_HOST_CHNL_CLASS = 0x2014;
+    CMD_BLE_READ_CHNL_MAP = 0x2015;
+    CMD_BLE_READ_REMOTE_FEAT = 0x2016;
+    CMD_BLE_ENCRYPT = 0x2017;
+    CMD_BLE_RAND = 0x2018;
+    CMD_BLE_START_ENC = 0x2019;
+    CMD_BLE_LTK_REQ_REPLY = 0x201A;
+    CMD_BLE_LTK_REQ_NEG_REPLY = 0x201B;
+    CMD_BLE_READ_SUPPORTED_STATES = 0x201C;
+    CMD_BLE_RECEIVER_TEST = 0x201D;
+    CMD_BLE_TRANSMITTER_TEST = 0x201E;
+    CMD_BLE_TEST_END = 0x201F;
+    CMD_BLE_RC_PARAM_REQ_REPLY = 0x2020;
+    CMD_BLE_RC_PARAM_REQ_NEG_REPLY = 0x2021;
+    CMD_BLE_SET_DATA_LENGTH = 0x2022;
+    CMD_BLE_READ_DEFAULT_DATA_LENGTH = 0x2023;
+    CMD_BLE_WRITE_DEFAULT_DATA_LENGTH = 0x2024;
+    CMD_BLE_GENERATE_DHKEY = 0x2026; // Not currently used in system/bt
+    CMD_BLE_ADD_DEV_RESOLVING_LIST = 0x2027;
+    CMD_BLE_RM_DEV_RESOLVING_LIST = 0x2028;
+    CMD_BLE_CLEAR_RESOLVING_LIST = 0x2029;
+    CMD_BLE_READ_RESOLVING_LIST_SIZE = 0x202A;
+    CMD_BLE_READ_RESOLVABLE_ADDR_PEER = 0x202B;
+    CMD_BLE_READ_RESOLVABLE_ADDR_LOCAL = 0x202C;
+    CMD_BLE_SET_ADDR_RESOLUTION_ENABLE = 0x202D;
+    CMD_BLE_SET_RAND_PRIV_ADDR_TIMOUT = 0x202E;
+    CMD_BLE_READ_MAXIMUM_DATA_LENGTH = 0x202F;
+    CMD_BLE_READ_PHY = 0x2030;
+    CMD_BLE_SET_DEFAULT_PHY = 0x2031;
+    CMD_BLE_SET_PHY = 0x2032;
+    CMD_BLE_ENH_RECEIVER_TEST = 0x2033;
+    CMD_BLE_ENH_TRANSMITTER_TEST = 0x2034;
+    CMD_BLE_SET_EXT_ADVERTISING_RANDOM_ADDRESS = 0x2035;
+    CMD_BLE_SET_EXT_ADVERTISING_PARAM = 0x2036;
+    CMD_BLE_SET_EXT_ADVERTISING_DATA = 0x2037;
+    CMD_BLE_SET_EXT_ADVERTISING_SCAN_RESP = 0x2038;
+    CMD_BLE_SET_EXT_ADVERTISING_ENABLE = 0x2039;
+    CMD_BLE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = 0x203A;
+    CMD_BLE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS = 0x203B;
+    CMD_BLE_REMOVE_ADVERTISING_SET = 0x203C;
+    CMD_BLE_CLEAR_ADVERTISING_SETS = 0x203D;
+    CMD_BLE_SET_PERIODIC_ADVERTISING_PARAM = 0x203E;
+    CMD_BLE_SET_PERIODIC_ADVERTISING_DATA = 0x203F;
+    CMD_BLE_SET_PERIODIC_ADVERTISING_ENABLE = 0x2040;
+    CMD_BLE_SET_EXTENDED_SCAN_PARAMETERS = 0x2041;
+    CMD_BLE_SET_EXTENDED_SCAN_ENABLE = 0x2042;
+    CMD_BLE_EXTENDED_CREATE_CONNECTION = 0x2043;
+    CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC = 0x2044;
+    CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = 0x2045;
+    CMD_BLE_PERIODIC_ADVERTISING_TERMINATE_SYNC = 0x2046;
+    CMD_BLE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST = 0x2047;
+    CMD_BLE_RM_DEVICE_FROM_PERIODIC_ADVERTISING_LIST = 0x2048;
+    CMD_BLE_CLEAR_PERIODIC_ADVERTISING_LIST = 0x2049;
+    CMD_BLE_READ_PERIODIC_ADVERTISING_LIST_SIZE = 0x204A;
+    CMD_BLE_READ_TRANSMIT_POWER = 0x204B;
+    CMD_BLE_READ_RF_COMPENS_POWER = 0x204C;
+    CMD_BLE_WRITE_RF_COMPENS_POWER = 0x204D;
+    CMD_BLE_SET_PRIVACY_MODE = 0x204E;
+    // Vendor specific commands 0xFC00 and above
+    // Android vendor specific commands defined in
+    // https://source.android.com/devices/bluetooth/hci_requirements#vendor-specific-capabilities
+    CMD_BLE_VENDOR_CAP = 0xFD53;
+    CMD_BLE_MULTI_ADV = 0xFD54;
+    CMD_BLE_BATCH_SCAN = 0xFD56;
+    CMD_BLE_ADV_FILTER = 0xFD57;
+    CMD_BLE_TRACK_ADV = 0xFD58;
+    CMD_BLE_ENERGY_INFO = 0xFD59;
+    CMD_BLE_EXTENDED_SCAN_PARAMS = 0xFD5A;
+    CMD_CONTROLLER_DEBUG_INFO = 0xFD5B;
+    CMD_CONTROLLER_A2DP_OPCODE = 0xFD5D;
+    CMD_BRCM_SET_ACL_PRIORITY = 0xFC57;
+    // Other vendor specific commands below here
+}
+
+// HCI event codes from the Bluetooth 5.0 specification Vol 2, Part 7, Section 7
+// Original definition: system/bt/stack/include/hcidefs.h
+enum EventEnum {
+    // Event is at most 1 byte (0xFF), thus 0xFFF must not be a valid value
+    EVT_UNKNOWN = 0xFFF;
+    EVT_INQUIRY_COMP = 0x01;
+    EVT_INQUIRY_RESULT = 0x02;
+    EVT_CONNECTION_COMP = 0x03;
+    EVT_CONNECTION_REQUEST = 0x04;
+    EVT_DISCONNECTION_COMP = 0x05;
+    EVT_AUTHENTICATION_COMP = 0x06;
+    EVT_RMT_NAME_REQUEST_COMP = 0x07;
+    EVT_ENCRYPTION_CHANGE = 0x08;
+    EVT_CHANGE_CONN_LINK_KEY = 0x09;
+    EVT_MASTER_LINK_KEY_COMP = 0x0A;
+    EVT_READ_RMT_FEATURES_COMP = 0x0B;
+    EVT_READ_RMT_VERSION_COMP = 0x0C;
+    EVT_QOS_SETUP_COMP = 0x0D;
+    EVT_COMMAND_COMPLETE = 0x0E;
+    EVT_COMMAND_STATUS = 0x0F;
+    EVT_HARDWARE_ERROR = 0x10;
+    EVT_FLUSH_OCCURED = 0x11;
+    EVT_ROLE_CHANGE = 0x12;
+    EVT_NUM_COMPL_DATA_PKTS = 0x13;
+    EVT_MODE_CHANGE = 0x14;
+    EVT_RETURN_LINK_KEYS = 0x15;
+    EVT_PIN_CODE_REQUEST = 0x16;
+    EVT_LINK_KEY_REQUEST = 0x17;
+    EVT_LINK_KEY_NOTIFICATION = 0x18;
+    EVT_LOOPBACK_COMMAND = 0x19;
+    EVT_DATA_BUF_OVERFLOW = 0x1A;
+    EVT_MAX_SLOTS_CHANGED = 0x1B;
+    EVT_READ_CLOCK_OFF_COMP = 0x1C;
+    EVT_CONN_PKT_TYPE_CHANGE = 0x1D;
+    EVT_QOS_VIOLATION = 0x1E;
+    EVT_PAGE_SCAN_MODE_CHANGE = 0x1F; // Deprecated
+    EVT_PAGE_SCAN_REP_MODE_CHNG = 0x20;
+    EVT_FLOW_SPECIFICATION_COMP = 0x21;
+    EVT_INQUIRY_RSSI_RESULT = 0x22;
+    EVT_READ_RMT_EXT_FEATURES_COMP = 0x23;
+    EVT_ESCO_CONNECTION_COMP = 0x2C;
+    EVT_ESCO_CONNECTION_CHANGED = 0x2D;
+    EVT_SNIFF_SUB_RATE = 0x2E;
+    EVT_EXTENDED_INQUIRY_RESULT = 0x2F;
+    EVT_ENCRYPTION_KEY_REFRESH_COMP = 0x30;
+    EVT_IO_CAPABILITY_REQUEST = 0x31;
+    EVT_IO_CAPABILITY_RESPONSE = 0x32;
+    EVT_USER_CONFIRMATION_REQUEST = 0x33;
+    EVT_USER_PASSKEY_REQUEST = 0x34;
+    EVT_REMOTE_OOB_DATA_REQUEST = 0x35;
+    EVT_SIMPLE_PAIRING_COMPLETE = 0x36;
+    EVT_LINK_SUPER_TOUT_CHANGED = 0x38;
+    EVT_ENHANCED_FLUSH_COMPLETE = 0x39;
+    EVT_USER_PASSKEY_NOTIFY = 0x3B;
+    EVT_KEYPRESS_NOTIFY = 0x3C;
+    EVT_RMT_HOST_SUP_FEAT_NOTIFY = 0x3D;
+    EVT_BLE_META = 0x3E;
+    EVT_PHYSICAL_LINK_COMP = 0x40;
+    EVT_CHANNEL_SELECTED = 0x41;
+    EVT_DISC_PHYSICAL_LINK_COMP = 0x42;
+    EVT_PHY_LINK_LOSS_EARLY_WARNING = 0x43;
+    EVT_PHY_LINK_RECOVERY = 0x44;
+    EVT_LOGICAL_LINK_COMP = 0x45;
+    EVT_DISC_LOGICAL_LINK_COMP = 0x46;
+    EVT_FLOW_SPEC_MODIFY_COMP = 0x47;
+    EVT_NUM_COMPL_DATA_BLOCKS = 0x48;
+    EVT_AMP_TEST_START = 0x49; // Not currently used in system/bt
+    EVT_AMP_TEST_END = 0x4A; // Not currently used in system/bt
+    EVT_AMP_RECEIVER_RPT = 0x4B; // Not currently used in system/bt
+    EVT_SHORT_RANGE_MODE_COMPLETE = 0x4C;
+    EVT_AMP_STATUS_CHANGE = 0x4D;
+    EVT_SET_TRIGGERED_CLOCK_CAPTURE = 0x4E;
+    EVT_SYNC_TRAIN_CMPL = 0x4F; // Not currently used in system/bt
+    EVT_SYNC_TRAIN_RCVD = 0x50; // Not currently used in system/bt
+    EVT_CONNLESS_SLAVE_BROADCAST_RCVD = 0x51; // Not currently used in system/bt
+    EVT_CONNLESS_SLAVE_BROADCAST_TIMEOUT = 0x52; // Not currently used in system/bt
+    EVT_TRUNCATED_PAGE_CMPL = 0x53; // Not currently used in system/bt
+    EVT_SLAVE_PAGE_RES_TIMEOUT = 0x54; // Not currently used in system/bt
+    EVT_CONNLESS_SLAVE_BROADCAST_CHNL_MAP_CHANGE = 0x55; // Not currently used in system/bt
+    EVT_INQUIRY_RES_NOTIFICATION = 0x56; // Not currently used in system/bt
+    EVT_AUTHED_PAYLOAD_TIMEOUT = 0x57; // Not currently used in system/bt
+    EVT_SAM_STATUS_CHANGE = 0x58; // Not currently used in system/bt
+}
+
+// Bluetooth low energy related meta event codes
+// from the Bluetooth 5.0 specification Vol 2, Part E, Section 7.7.65
+// Original definition: system/bt/stack/include/hcidefs.h
+enum BleMetaEventEnum {
+    // BLE meta event code is at most 1 byte (0xFF), thus 0xFFF must not be a valid value
+    BLE_EVT_UNKNOWN = 0xFFF;
+    BLE_EVT_CONN_COMPLETE_EVT = 0x01;
+    BLE_EVT_ADV_PKT_RPT_EVT = 0x02;
+    BLE_EVT_LL_CONN_PARAM_UPD_EVT = 0x03;
+    BLE_EVT_READ_REMOTE_FEAT_CMPL_EVT = 0x04;
+    BLE_EVT_LTK_REQ_EVT = 0x05;
+    BLE_EVT_RC_PARAM_REQ_EVT = 0x06;
+    BLE_EVT_DATA_LENGTH_CHANGE_EVT = 0x07;
+    BLE_EVT_READ_LOCAL_P256_PUB_KEY = 0x08; // Not currently used in system/bt
+    BLE_EVT_GEN_DHKEY_CMPL = 0x09; // Not currently used in system/bt
+    BLE_EVT_ENHANCED_CONN_COMPLETE_EVT = 0x0a;
+    BLE_EVT_DIRECT_ADV_EVT = 0x0b;
+    BLE_EVT_PHY_UPDATE_COMPLETE_EVT = 0x0c;
+    BLE_EVT_EXTENDED_ADVERTISING_REPORT_EVT = 0x0D;
+    BLE_EVT_PERIODIC_ADV_SYNC_EST_EVT = 0x0E;
+    BLE_EVT_PERIODIC_ADV_REPORT_EVT = 0x0F;
+    BLE_EVT_PERIODIC_ADV_SYNC_LOST_EVT = 0x10;
+    BLE_EVT_SCAN_TIMEOUT_EVT = 0x11;
+    BLE_EVT_ADVERTISING_SET_TERMINATED_EVT = 0x12;
+    BLE_EVT_SCAN_REQ_RX_EVT = 0x13;
+    BLE_EVT_CHNL_SELECTION_ALGORITHM = 0x14; // Not currently used in system/bt
+}
+
+// HCI status code from the Bluetooth 5.0 specification Vol 2, Part D.
+// Original definition: system/bt/stack/include/hcidefs.h
+enum StatusEnum {
+    // Status is at most 1 byte (0xFF), thus 0xFFF must not be a valid value
+    STATUS_UNKNOWN = 0xFFF;
+    STATUS_SUCCESS = 0x00;
+    STATUS_ILLEGAL_COMMAND = 0x01;
+    STATUS_NO_CONNECTION = 0x02;
+    STATUS_HW_FAILURE = 0x03;
+    STATUS_PAGE_TIMEOUT = 0x04;
+    STATUS_AUTH_FAILURE = 0x05;
+    STATUS_KEY_MISSING = 0x06;
+    STATUS_MEMORY_FULL = 0x07;
+    STATUS_CONNECTION_TOUT = 0x08;
+    STATUS_MAX_NUM_OF_CONNECTIONS = 0x09;
+    STATUS_MAX_NUM_OF_SCOS = 0x0A;
+    STATUS_CONNECTION_EXISTS = 0x0B;
+    STATUS_COMMAND_DISALLOWED = 0x0C;
+    STATUS_HOST_REJECT_RESOURCES = 0x0D;
+    STATUS_HOST_REJECT_SECURITY = 0x0E;
+    STATUS_HOST_REJECT_DEVICE = 0x0F;
+    STATUS_HOST_TIMEOUT = 0x10;
+    STATUS_UNSUPPORTED_VALUE = 0x11;
+    STATUS_ILLEGAL_PARAMETER_FMT = 0x12;
+    STATUS_PEER_USER = 0x13;
+    STATUS_PEER_LOW_RESOURCES = 0x14;
+    STATUS_PEER_POWER_OFF = 0x15;
+    STATUS_CONN_CAUSE_LOCAL_HOST = 0x16;
+    STATUS_REPEATED_ATTEMPTS = 0x17;
+    STATUS_PAIRING_NOT_ALLOWED = 0x18;
+    STATUS_UNKNOWN_LMP_PDU = 0x19;
+    STATUS_UNSUPPORTED_REM_FEATURE = 0x1A;
+    STATUS_SCO_OFFSET_REJECTED = 0x1B;
+    STATUS_SCO_INTERVAL_REJECTED = 0x1C;
+    STATUS_SCO_AIR_MODE = 0x1D;
+    STATUS_INVALID_LMP_PARAM = 0x1E;
+    STATUS_UNSPECIFIED = 0x1F;
+    STATUS_UNSUPPORTED_LMP_FEATURE = 0x20;
+    STATUS_ROLE_CHANGE_NOT_ALLOWED = 0x21;
+    STATUS_LMP_RESPONSE_TIMEOUT = 0x22;
+    STATUS_LMP_STATUS_TRANS_COLLISION = 0x23;
+    STATUS_LMP_PDU_NOT_ALLOWED = 0x24;
+    STATUS_ENCRY_MODE_NOT_ACCEPTABLE = 0x25;
+    STATUS_UNIT_KEY_USED = 0x26;
+    STATUS_QOS_NOT_SUPPORTED = 0x27;
+    STATUS_INSTANT_PASSED = 0x28;
+    STATUS_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29;
+    STATUS_DIFF_TRANSACTION_COLLISION = 0x2A;
+    STATUS_UNDEFINED_0x2B = 0x2B; // Not used
+    STATUS_QOS_UNACCEPTABLE_PARAM = 0x2C;
+    STATUS_QOS_REJECTED = 0x2D;
+    STATUS_CHAN_CLASSIF_NOT_SUPPORTED = 0x2E;
+    STATUS_INSUFFCIENT_SECURITY = 0x2F;
+    STATUS_PARAM_OUT_OF_RANGE = 0x30;
+    STATUS_UNDEFINED_0x31 = 0x31; // Not used
+    STATUS_ROLE_SWITCH_PENDING = 0x32;
+    STATUS_UNDEFINED_0x33 = 0x33;
+    STATUS_RESERVED_SLOT_VIOLATION = 0x34;
+    STATUS_ROLE_SWITCH_FAILED = 0x35;
+    STATUS_INQ_RSP_DATA_TOO_LARGE = 0x36;
+    STATUS_SIMPLE_PAIRING_NOT_SUPPORTED = 0x37;
+    STATUS_HOST_BUSY_PAIRING = 0x38;
+    STATUS_REJ_NO_SUITABLE_CHANNEL = 0x39;
+    STATUS_CONTROLLER_BUSY = 0x3A;
+    STATUS_UNACCEPT_CONN_INTERVAL = 0x3B;
+    STATUS_ADVERTISING_TIMEOUT = 0x3C;
+    STATUS_CONN_TOUT_DUE_TO_MIC_FAILURE = 0x3D;
+    STATUS_CONN_FAILED_ESTABLISHMENT = 0x3E;
+    STATUS_MAC_CONNECTION_FAILED = 0x3F;
+    STATUS_LT_ADDR_ALREADY_IN_USE = 0x40;
+    STATUS_LT_ADDR_NOT_ALLOCATED = 0x41;
+    STATUS_CLB_NOT_ENABLED = 0x42;
+    STATUS_CLB_DATA_TOO_BIG = 0x43;
+    STATUS_OPERATION_CANCELED_BY_HOST = 0x44; // Not currently used in system/bt
+}
diff --git a/core/proto/android/bluetooth/hfp/enums.proto b/core/proto/android/bluetooth/hfp/enums.proto
new file mode 100644
index 0000000..d286e4b
--- /dev/null
+++ b/core/proto/android/bluetooth/hfp/enums.proto
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+package android.bluetooth.hfp;
+
+option java_outer_classname = "BluetoothHfpProtoEnums";
+option java_multiple_files = true;
+
+enum ScoCodec {
+    SCO_CODEC_UNKNOWN = 0;
+    SCO_CODEC_CVSD = 1;
+    // Default codec behind Wide Band Speech
+    SCO_CODEC_MSBC = 2;
+}
\ No newline at end of file
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index cc5aa20..4158577 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -436,12 +436,19 @@
         // Ordered GPU debug layer list for GLES
         // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers_gles = 7;
-        // GUP - List of Apps selected to use Game Update Packages
-        optional SettingProto gup_dev_opt_in_apps = 8;
-        // GUP - List of Apps selected not to use Game Update Packages
-        optional SettingProto gup_dev_opt_out_apps = 9;
-        // GUP - List of Apps that are forbidden to use Game Update Packages
-        optional SettingProto gup_black_list = 10;
+        // GUP - Game Update Package global preference for all Apps
+        // 0 = Default
+        // 1 = All Apps use Game Update Package
+        // 2 = All Apps use system graphics driver
+        optional SettingProto gup_dev_all_apps = 8;
+        // GUP - List of Apps selected to use Game Update Package
+        // i.e. <pkg1>,<pkg2>,...,<pkgN>
+        optional SettingProto gup_dev_opt_in_apps = 9;
+        // GUP - List of Apps selected not to use Game Update Package
+        // i.e. <pkg1>,<pkg2>,...,<pkgN>
+        optional SettingProto gup_dev_opt_out_apps = 10;
+        // GUP - List of Apps that are forbidden to use Game Update Package
+        optional SettingProto gup_blacklist = 11;
     }
     optional Gpu gpu = 59;
 
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 9f4345d..4bfd4d2 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -182,6 +182,7 @@
         optional SettingProto pulse_on_pick_up = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto pulse_on_long_press = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto pulse_on_double_tap = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto pulse_on_tap = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Doze doze = 21;
 
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 0ec8c1a..7f3ea7a 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -403,18 +403,23 @@
         optional bool is_charging = 1;
         optional bool is_in_parole = 2;
 
+        // List of UIDs currently in the foreground.
+        repeated int32 foreground_uids = 3;
+
         message TrackedJob {
             option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
             optional JobStatusShortInfoProto info = 1;
             optional int32 source_uid = 2;
             optional JobStatusDumpProto.Bucket effective_standby_bucket = 3;
-            optional bool has_quota = 4;
+            // If the job started while the app was in the TOP state.
+            optional bool is_top_started_job = 4;
+            optional bool has_quota = 5;
             // The amount of time that this job has remaining in its quota. This
             // can be negative if the job is out of quota.
-            optional int64 remaining_quota_ms = 5;
+            optional int64 remaining_quota_ms = 6;
         }
-        repeated TrackedJob tracked_jobs = 3;
+        repeated TrackedJob tracked_jobs = 4;
 
         message Package {
             option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -456,7 +461,7 @@
 
             repeated TimingSession saved_sessions = 3;
         }
-        repeated PackageStats package_stats = 4;
+        repeated PackageStats package_stats = 5;
     }
     message StorageController {
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2f3a491..f3e3241 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1186,6 +1186,7 @@
     <!-- Used for permissions that are associated with activity recognition.
          TODO(zezeozue). STOPSHIP: Add icon -->
     <permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
+        android:icon="@drawable/perm_group_activity_recognition"
         android:label="@string/permgrouplab_activityRecognition"
         android:description="@string/permgroupdesc_activityRecognition"
         android:request="@string/permgrouprequest_activityRecognition"
@@ -2532,6 +2533,16 @@
     <permission android:name="android.permission.WRITE_GSERVICES"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi @hide Allows an application to modify config settings.
+    <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.WRITE_DEVICE_CONFIG"
+        android:protectionLevel="signature|configurator"/>
+
+    <!-- @SystemApi @hide Allows an application to read config settings.
+    <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.READ_DEVICE_CONFIG"
+        android:protectionLevel="signature|preinstalled" />
+
     <!-- @SystemApi @TestApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
@@ -3196,9 +3207,10 @@
 
     <!-- @SystemApi Required to add or remove another application as a device admin.
          <p>Not for use by third-party applications.
-         @hide -->
+         @hide
+         @removed -->
     <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature" />
 
     <!-- @SystemApi Allows an app to reset the device password.
          <p>Not for use by third-party applications.
@@ -3520,19 +3532,25 @@
     <permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to provide remote displays.
+         <p>Not for use by third-party applications.</p>
+         @hide -->
+    <permission android:name="android.permission.REMOTE_DISPLAY_PROVIDER"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Allows an application to capture video output.
          <p>Not for use by third-party applications.</p>
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to capture secure video output.
          <p>Not for use by third-party applications.</p>
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature" />
 
     <!-- Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
diff --git a/core/res/res/drawable/perm_group_activity_recognition.xml b/core/res/res/drawable/perm_group_activity_recognition.xml
new file mode 100644
index 0000000..0ade6c6
--- /dev/null
+++ b/core/res/res/drawable/perm_group_activity_recognition.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1
+2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9
+0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2
+2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" />
+</vector>
diff --git a/core/res/res/drawable/perm_group_sensors.xml b/core/res/res/drawable/perm_group_sensors.xml
index ce36c13..e4663d7 100644
--- a/core/res/res/drawable/perm_group_sensors.xml
+++ b/core/res/res/drawable/perm_group_sensors.xml
@@ -19,11 +19,11 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
-
-    <path
-        android:fillColor="#000000"
-        android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1
-2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9
-0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2
-2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" />
-</vector>
\ No newline at end of file
+  <path
+      android:fillColor="#000000"
+      android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3C4.42,3 2,5.42 2,
+                        8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5C22,
+                        5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1l-0.1,-0.1C7.14,14.24 4,11.39 4,8.5C4,6.5 5.5,
+                        5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5C20,
+                        11.39 16.86,14.24 12.1,18.55z"/>
+</vector>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 18a42bc..b15f72e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -274,6 +274,9 @@
         <!-- Additional flag from base permission type: this permission can be automatically
             granted to the document manager -->
         <flag name="documenter" value="0x40000" />
+        <!-- Additional flag from base permission type: this permission automatically
+            granted to device configurator -->
+        <flag name="configurator" value="0x80000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2e3bd7c..64fdc02 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -618,15 +618,6 @@
     <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
     <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
 
-    <!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario
-         where the chipset does not support background scanning (config_wifi_background_scan_suport
-         is false) to set up a periodic wake up scan so that the device can connect to a new access
-         point on the move. A value of 0 means no periodic scans will be used in the framework. -->
-    <integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
-
-    <!-- Integer indicating the framework no networks periodic scan interval in milliseconds. -->
-    <integer translatable="false" name="config_wifi_no_network_periodic_scan_interval">300000</integer>
-
     <!-- Integer indicating disconnect mode short scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_disconnected_short_scan_interval">15000</integer>
 
@@ -692,6 +683,11 @@
     <!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
     <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
 
+    <!-- Channel list restriction to Automatic channel selection (ACS) for softap. If the device
+         doesn't want to restrict channels this should be empty. Value is a comma separated channel
+         string and/or channel range string like '1-6,11' -->
+    <string translatable="false" name="config_wifi_softap_acs_supported_channel_list"></string>
+
     <!-- Wifi driver supports IEEE80211AC for softap -->
     <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
 
@@ -699,6 +695,9 @@
          for automotive builds only (the one that have PackageManager#FEATURE_AUTOMOTIVE) -->
     <bool translatable="false" name="config_wifi_local_only_hotspot_5ghz">false</bool>
 
+    <!-- Indicates that connected MAC randomization is supported on this device -->
+    <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool>
+
     <!-- Flag indicating whether we should enable the automatic brightness.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
@@ -1689,6 +1688,8 @@
          config_enableFusedLocationOverlay is false. -->
     <string name="config_fusedLocationProviderPackageName" translatable="false">com.android.location.fused</string>
 
+    <string-array name="config_locationExtraPackageNames" translatable="false"></string-array>
+
     <!-- The package name of the default network recommendation app.
          A network recommendation provider must:
              * Be granted the SCORE_NETWORKS permission.
@@ -1890,6 +1891,8 @@
                cell broadcasting sms, and MMS. -->
     <bool name="config_sms_capable">true</bool>
 
+    <!-- TODO: STOPSHIP(b/110557011): Remove this from framework and overlays as we use
+         config_defaultRoleHolders now. -->
     <!-- Default SMS Application. This will be the default SMS application when
          the phone first boots. The user can then change the default app to one
          of their choosing.
@@ -1908,6 +1911,12 @@
          the behavior will be as though no app was named as an explicit default. -->
     <string name="default_browser" translatable="false"></string>
 
+    <!-- Default role holders. This will be an array of roles and package names of their default
+         holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". -->
+    <string-array name="config_defaultRoleHolders" translatable="false">
+        <item>android.app.role.SMS: com.android.messaging</item>
+    </string-array>
+
     <!-- Enable/disable default bluetooth profiles:
         HSP_AG, ObexObjectPush, Audio, NAP -->
     <bool name="config_bluetooth_default_profiles">true</bool>
@@ -2203,6 +2212,9 @@
     <!-- Type of the double tap sensor. Empty if double tap is not supported. -->
     <string name="config_dozeDoubleTapSensorType" translatable="false"></string>
 
+    <!-- Type of the tap sensor. Empty if tap is not supported. -->
+    <string name="config_dozeTapSensorType" translatable="false"></string>
+
     <!-- Type of the long press sensor. Empty if long press is not supported. -->
     <string name="config_dozeLongPressSensorType" translatable="false"></string>
 
@@ -2800,6 +2812,9 @@
     <!-- Flag indicating which package name can access the persistent data partition -->
     <string name="config_persistentDataPackageName" translatable="false"></string>
 
+    <!-- Flag indicating which package name can access DeviceConfig table -->
+    <string name="config_deviceConfiguratorPackageName" translatable="false"></string>
+
     <!-- Flag indicating apps will skip sending hold request before merge. In this case
         IMS service implementation will do both.i.e.hold followed by merge. -->
     <bool name="skipHoldBeforeMerge">true</bool>
@@ -3696,7 +3711,7 @@
     <string name="config_inputEventCompatProcessorOverrideClassName" translatable="false"></string>
 
     <!-- Component name for the default module metadata provider on this device -->
-    <string name="config_defaultModuleMetadataProvider">com.android.modulemetadata</string>
+    <string name="config_defaultModuleMetadataProvider" translatable="false">com.android.modulemetadata</string>
 
     <!-- This is the default launcher component to use on secondary displays that support system
          decorations.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index b3b30e9..777886a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2985,6 +2985,11 @@
         <public name="system_notification_accent_color" />
     </public-group>
 
+    <public-group type="array" first-id="0x01070006">
+      <!-- @hide @SystemApi -->
+      <public name="config_defaultRoleHolders" />
+    </public-group>
+
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index daf8b44..9317cff 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -325,6 +325,7 @@
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
   <java-symbol type="bool" name="config_wifi_softap_acs_supported" />
+  <java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
   <java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" />
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
@@ -458,9 +459,7 @@
   <java-symbol type="integer" name="config_toastDefaultGravity" />
   <java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
   <java-symbol type="integer" name="config_shortPressOnSleepBehavior" />
-  <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
-  <java-symbol type="integer" name="config_wifi_no_network_periodic_scan_interval" />
   <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
   <java-symbol type="integer" name="config_windowOutsetBottom" />
   <java-symbol type="integer" name="db_connection_pool_size" />
@@ -1840,6 +1839,7 @@
   <java-symbol type="array" name="radioAttributes" />
   <java-symbol type="array" name="config_oemUsbModeOverride" />
   <java-symbol type="array" name="config_locationProviderPackageNames" />
+  <java-symbol type="array" name="config_locationExtraPackageNames" />
   <java-symbol type="array" name="config_testLocationProviders" />
   <java-symbol type="array" name="config_defaultNotificationVibePattern" />
   <java-symbol type="array" name="config_notificationFallbackVibePattern" />
@@ -1879,6 +1879,7 @@
   <java-symbol type="bool" name="config_wifi_dual_band_support" />
   <java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" />
   <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" />
+  <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" />
   <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
@@ -2139,6 +2140,7 @@
   <java-symbol type="string" name="config_carrierAppInstallDialogComponent" />
   <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
   <java-symbol type="string" name="config_persistentDataPackageName" />
+  <java-symbol type="string" name="config_deviceConfiguratorPackageName" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
@@ -3001,6 +3003,7 @@
   <java-symbol type="array" name="config_emergency_mcc_codes" />
 
   <java-symbol type="string" name="config_dozeDoubleTapSensorType" />
+  <java-symbol type="string" name="config_dozeTapSensorType" />
   <java-symbol type="bool" name="config_dozePulsePickup" />
 
   <!-- Used for MimeIconUtils. -->
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 74943c7..0fc3bd2 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -36,12 +36,12 @@
     frameworks-core-util-lib \
     mockwebserver \
     guava \
-    android-support-test \
+    androidx.test.runner \
+    androidx.test.rules \
     mockito-target-minus-junit4 \
     espresso-core \
     ub-uiautomator \
     platform-test-annotations \
-    compatibility-device-util \
     truth-prebuilt \
     print-test-util-lib \
     testng # TODO: remove once Android migrates to JUnit 4.12, which provide assertThrows
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 46d4a47..86818c6 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -56,6 +56,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.READ_DREAM_STATE" />
     <uses-permission android:name="android.permission.WRITE_DREAM_STATE" />
     <uses-permission android:name="android.permission.READ_LOGS"/>
@@ -65,6 +66,7 @@
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
@@ -1425,7 +1427,7 @@
 
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.frameworks.coretests"
             android:label="Frameworks Core Tests" />
     <key-sets>
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 68ef34b..b40aa87 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -25,6 +25,7 @@
     <option name="test-tag" value="FrameworksCoreTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.coretests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java
index e26bdf5..be1d44c 100644
--- a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java
@@ -13,17 +13,17 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
+
 package android.animation;
 
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
 
+import androidx.test.filters.LargeTest;
+
+import com.android.frameworks.coretests.R;
+
 import java.util.HashSet;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import com.android.frameworks.coretests.R;
 
 @LargeTest
 public class AnimatorInflaterTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity>  {
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivity.java b/core/tests/coretests/src/android/animation/AnimatorSetActivity.java
index 501ea48..af265af 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetActivity.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetActivity.java
@@ -1,10 +1,26 @@
-package android.animation;
+/*
+ * 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.
+ */
 
-import com.android.frameworks.coretests.R;
+package android.animation;
 
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class AnimatorSetActivity extends Activity {
     @Override
     public void onCreate(Bundle savedBundleInstance) {
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
index 922bc59..55837ba 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
@@ -1,12 +1,29 @@
+/*
+ * 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.
+ */
+
 package android.animation;
 
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.frameworks.coretests.R;
+
 import java.util.ArrayList;
 
 public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
index 7eb32ee..4e90d1a 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetEventsTest.java
@@ -13,12 +13,14 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
+
 package android.animation;
 
 import android.os.Handler;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.widget.Button;
+
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.util.concurrent.TimeUnit;
diff --git a/core/tests/coretests/src/android/animation/AutoCancelTest.java b/core/tests/coretests/src/android/animation/AutoCancelTest.java
index b1f88db..b3ec92c 100644
--- a/core/tests/coretests/src/android/animation/AutoCancelTest.java
+++ b/core/tests/coretests/src/android/animation/AutoCancelTest.java
@@ -13,11 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import java.util.HashMap;
 import java.util.concurrent.TimeUnit;
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
index 0e1e6ac..2b9866d 100644
--- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -13,14 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.animation;
 
-import com.android.frameworks.coretests.R;
+package android.animation;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.widget.Button;
 
+import com.android.frameworks.coretests.R;
+
 public class BasicAnimatorActivity extends Activity {
     public Button mAnimatingButton;
     @Override
diff --git a/core/tests/coretests/src/android/animation/EventsTest.java b/core/tests/coretests/src/android/animation/EventsTest.java
index 28cfe3d..ba7413a 100644
--- a/core/tests/coretests/src/android/animation/EventsTest.java
+++ b/core/tests/coretests/src/android/animation/EventsTest.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
 
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
diff --git a/core/tests/coretests/src/android/animation/FutureWaiter.java b/core/tests/coretests/src/android/animation/FutureWaiter.java
index 0c65e20..0c09a4a 100644
--- a/core/tests/coretests/src/android/animation/FutureWaiter.java
+++ b/core/tests/coretests/src/android/animation/FutureWaiter.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 import com.google.common.util.concurrent.AbstractFuture;
diff --git a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
index 606a939..53f9472 100644
--- a/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
+++ b/core/tests/coretests/src/android/animation/ObjectAnimatorEventsTest.java
@@ -13,9 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 import android.widget.Button;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/animation/StateListAnimatorTest.java b/core/tests/coretests/src/android/animation/StateListAnimatorTest.java
index a9961e1..e755b89 100644
--- a/core/tests/coretests/src/android/animation/StateListAnimatorTest.java
+++ b/core/tests/coretests/src/android/animation/StateListAnimatorTest.java
@@ -14,16 +14,16 @@
 * limitations under the License.
 */
 
-
 package android.animation;
 
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
 import android.util.StateSet;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.util.concurrent.atomic.AtomicInteger;
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
index c25d050..f6d71b8 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorEventsTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 /**
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 4facf77..dee0a3e 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -13,8 +13,11 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
+
 package android.animation;
 
+import static android.test.MoreAsserts.assertNotEqual;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -24,23 +27,20 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.Choreographer;
 import android.view.animation.LinearInterpolator;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 
-import static android.test.MoreAsserts.assertNotEqual;
-
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class ValueAnimatorTests {
diff --git a/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java b/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java
index 30ec182..997af00 100644
--- a/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java
+++ b/core/tests/coretests/src/android/animation/ViewPropertyAnimatorTest.java
@@ -13,15 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.animation;
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.ViewPropertyAnimator;
 import android.widget.Button;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.util.concurrent.TimeUnit;
diff --git a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
index 19a390a..8dc5ad6 100644
--- a/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationErrorReportTest.java
@@ -16,16 +16,17 @@
 
 package android.app;
 
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.app.ApplicationErrorReport.CrashInfo;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.app.ApplicationErrorReport.CrashInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class ApplicationErrorReportTest {
diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
index 063bef7..4b0ed65 100644
--- a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
@@ -16,13 +16,17 @@
 
 package android.app;
 
+import static android.os.storage.VolumeInfo.STATE_MOUNTED;
+import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
@@ -32,9 +36,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import static android.os.storage.VolumeInfo.STATE_MOUNTED;
-import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
-
 @LargeTest
 public class ApplicationPackageManagerTest extends TestCase {
     private static final String sInternalVolPath = "/data";
diff --git a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
index c1d4be0..33e0402 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java
@@ -22,7 +22,8 @@
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import com.google.mockwebserver.MockResponse;
 
diff --git a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
index 39d9a8e..adfe76f 100644
--- a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
@@ -23,10 +23,11 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.StatFs;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.Suppress;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
diff --git a/core/tests/coretests/src/android/app/InstrumentationTest.java b/core/tests/coretests/src/android/app/InstrumentationTest.java
index 9b59da4..93b5aec 100644
--- a/core/tests/coretests/src/android/app/InstrumentationTest.java
+++ b/core/tests/coretests/src/android/app/InstrumentationTest.java
@@ -17,9 +17,10 @@
 package android.app;
 
 import android.os.Bundle;
-import android.support.test.filters.LargeTest;
 import android.test.InstrumentationTestCase;
 
+import androidx.test.filters.LargeTest;
+
 @LargeTest
 public class InstrumentationTest extends InstrumentationTestCase {
 
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index c83e798..e343383 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package android.app;
 
 import static junit.framework.TestCase.assertNotNull;
@@ -27,11 +26,12 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcelable;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index e89a4d3..c17aa92 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -33,11 +33,12 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.widget.RemoteViews;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/SearchManagerTest.java b/core/tests/coretests/src/android/app/SearchManagerTest.java
index 08b7f60..14370c8 100644
--- a/core/tests/coretests/src/android/app/SearchManagerTest.java
+++ b/core/tests/coretests/src/android/app/SearchManagerTest.java
@@ -17,17 +17,13 @@
 package android.app;
 
 import android.app.activity.LocalActivity;
-
-import android.app.Activity;
-import android.app.ISearchManager;
-import android.app.SearchManager;
-import android.app.SearchableInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.os.ServiceManager;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 /**
  * To launch this test from the command line:
diff --git a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
index 61d73bc..bbd442d 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityManagerTest.java
@@ -21,8 +21,9 @@
 import android.content.pm.ConfigurationInfo;
 import android.content.res.Configuration;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
 
 import java.util.Iterator;
 import java.util.List;
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 0f83a29..9cb3489 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -36,13 +36,14 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.IBinder;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.MergedConfiguration;
 import android.view.Display;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/app/activity/BroadcastTest.java b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
index 13e70eb..0f81896 100644
--- a/core/tests/coretests/src/android/app/activity/BroadcastTest.java
+++ b/core/tests/coretests/src/android/app/activity/BroadcastTest.java
@@ -27,11 +27,10 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.UserHandle;
-import android.support.test.filters.LargeTest;
-import android.test.FlakyTest;
 import android.util.Log;
 
-import java.util.Arrays;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.LargeTest;
 
 @LargeTest
 public class BroadcastTest extends ActivityTestsBase {
@@ -231,7 +230,7 @@
     };
 
     // Mark flaky until http://b/issue?id=1191607 is resolved.
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     public void testRegistered() throws Exception {
         runLaunchpad(LaunchpadActivity.BROADCAST_REGISTERED);
     }
@@ -248,12 +247,12 @@
         runLaunchpad(LaunchpadActivity.BROADCAST_ABORT);
     }
 
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     public void testAll() throws Exception {
         runLaunchpad(LaunchpadActivity.BROADCAST_ALL);
     }
 
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     public void testMulti() throws Exception {
         runLaunchpad(LaunchpadActivity.BROADCAST_MULTI);
     }
@@ -348,7 +347,7 @@
     }
 
     // Marking flaky until http://b/issue?id=1191337 is resolved
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     public void testReceiveSticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
@@ -358,7 +357,7 @@
     }
 
     // Marking flaky until http://b/issue?id=1191337 is resolved
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     public void testReceive2Sticky() throws Exception {
         Intent intent = new Intent(LaunchpadActivity.BROADCAST_STICKY1, null);
         intent.putExtra("test", LaunchpadActivity.DATA_1);
diff --git a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
index 8c1d79b..19ddb52 100644
--- a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
+++ b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
@@ -21,7 +21,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 @LargeTest
 public class IntentSenderTest extends BroadcastTest {
diff --git a/core/tests/coretests/src/android/app/activity/LaunchTest.java b/core/tests/coretests/src/android/app/activity/LaunchTest.java
index 5b86dce..6846ea7 100644
--- a/core/tests/coretests/src/android/app/activity/LaunchTest.java
+++ b/core/tests/coretests/src/android/app/activity/LaunchTest.java
@@ -17,8 +17,9 @@
 package android.app.activity;
 
 import android.content.ComponentName;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.Suppress;
 
 @Suppress  // Flaky.
 public class LaunchTest extends ActivityTestsBase {
diff --git a/core/tests/coretests/src/android/app/activity/LifecycleTest.java b/core/tests/coretests/src/android/app/activity/LifecycleTest.java
index ed01fac5..5aa0380 100644
--- a/core/tests/coretests/src/android/app/activity/LifecycleTest.java
+++ b/core/tests/coretests/src/android/app/activity/LifecycleTest.java
@@ -18,8 +18,9 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 public class LifecycleTest extends ActivityTestsBase {
     private Intent mTopIntent;
diff --git a/core/tests/coretests/src/android/app/activity/MetaDataTest.java b/core/tests/coretests/src/android/app/activity/MetaDataTest.java
index 5b9c0e9..cf27878 100644
--- a/core/tests/coretests/src/android/app/activity/MetaDataTest.java
+++ b/core/tests/coretests/src/android/app/activity/MetaDataTest.java
@@ -27,8 +27,11 @@
 import android.content.res.XmlResourceParser;
 import android.os.Bundle;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
diff --git a/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
index 9f402a5..8184627 100644
--- a/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
@@ -1,19 +1,18 @@
-/* //device/apps/AndroidTests/src/com.android.unit_tests/activity/TestedScreen.java
-**
-** Copyright 2006, 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.
-*/
+/*
+ * Copyright (C) 2006 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.app.activity;
 
@@ -21,7 +20,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Process;
-import android.util.Log;
+
+//device/apps/AndroidTests/src/com.android.unit_tests/activity/TestedScreen.java
 
 public class RemoteSubActivityScreen extends SubActivityScreen {
     Handler mHandler = new Handler();
diff --git a/core/tests/coretests/src/android/app/activity/ServiceTest.java b/core/tests/coretests/src/android/app/activity/ServiceTest.java
index d3ae415..9d2aebd 100644
--- a/core/tests/coretests/src/android/app/activity/ServiceTest.java
+++ b/core/tests/coretests/src/android/app/activity/ServiceTest.java
@@ -22,13 +22,12 @@
 import android.content.ServiceConnection;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.util.Log;
+import android.os.RemoteException;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 // These test binders purport to support an interface whose canonical
 // interface name is ServiceTest.SERVICE_LOCAL
diff --git a/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java
index 41b9547..8e17295 100644
--- a/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java
+++ b/core/tests/coretests/src/android/app/activity/SetTimeZonePermissionsTest.java
@@ -19,7 +19,8 @@
 import android.app.AlarmManager;
 import android.content.Context;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import java.util.TimeZone;
 
diff --git a/core/tests/coretests/src/android/app/activity/SubActivityTest.java b/core/tests/coretests/src/android/app/activity/SubActivityTest.java
index 35dde8a..53f89fe 100644
--- a/core/tests/coretests/src/android/app/activity/SubActivityTest.java
+++ b/core/tests/coretests/src/android/app/activity/SubActivityTest.java
@@ -16,9 +16,10 @@
 
 package android.app.activity;
 
-import android.test.suitebuilder.annotation.Suppress;
 import android.content.ComponentName;
 
+import androidx.test.filters.Suppress;
+
 @Suppress
 public class SubActivityTest extends ActivityTestsBase {
 
diff --git a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
index 9b5b725..8d42c74 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
@@ -27,8 +27,9 @@
 
 import android.app.admin.PasswordMetrics.PasswordComplexityBucket;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
index 689e683..1f4e5df 100644
--- a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
+++ b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.app.assist;
 
 import static android.view.View.AUTOFILL_TYPE_TEXT;
@@ -22,13 +23,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.assist.AssistStructure.ViewNode;
-import android.content.ComponentName;
 import android.content.Context;
 import android.os.Parcel;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.InputFilter;
 import android.util.Log;
 import android.view.autofill.AutofillId;
@@ -37,6 +34,10 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java b/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java
index f4b6bed..defec43 100644
--- a/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java
+++ b/core/tests/coretests/src/android/app/assist/EmptyLayoutActivity.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.app.assist;
 
 import android.app.Activity;
diff --git a/core/tests/coretests/src/android/app/backup/BackupDataTest.java b/core/tests/coretests/src/android/app/backup/BackupDataTest.java
index 5b8e481..18ff54f 100644
--- a/core/tests/coretests/src/android/app/backup/BackupDataTest.java
+++ b/core/tests/coretests/src/android/app/backup/BackupDataTest.java
@@ -16,31 +16,22 @@
 
 package android.app.backup;
 
-import android.app.backup.BackupDataInput;
-import android.app.backup.BackupDataOutput;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
-import android.test.InstrumentationTestCase;
 import android.util.Base64;
-import android.util.Log;
-import org.json.JSONObject;
+
+import androidx.test.filters.LargeTest;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileReader;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.lang.Exception;
-import java.nio.ByteBuffer;
 
 @LargeTest
 public class BackupDataTest extends AndroidTestCase {
diff --git a/core/tests/coretests/src/android/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
index 5db416b..08edb4e 100644
--- a/core/tests/coretests/src/android/app/backup/FullBackupTest.java
+++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
@@ -18,11 +18,12 @@
 
 import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags;
 import android.content.Context;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
+import androidx.test.filters.LargeTest;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlPullParserFactory;
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
index b1f8552..52b2658 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionTests.java
@@ -23,8 +23,9 @@
 import android.app.ClientTransactionHandler;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index fb0f534..ad28d13 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -35,8 +35,9 @@
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index a788a93..f730a24 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -45,10 +45,11 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 2801f324..8604b0c 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -50,8 +50,9 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.app.IVoiceInteractor;
 
diff --git a/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
index e20645c..0efc0ab 100644
--- a/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
+++ b/core/tests/coretests/src/android/app/timezone/DistroFormatVersionTest.java
@@ -21,7 +21,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import org.junit.Test;
 
diff --git a/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
index b69054c..b519bf8 100644
--- a/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
+++ b/core/tests/coretests/src/android/app/timezone/DistroRulesVersionTest.java
@@ -21,7 +21,8 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import org.junit.Test;
 
diff --git a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
index dd46240..bb535b6 100644
--- a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
+++ b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
@@ -16,14 +16,13 @@
 
 package android.app.timezone;
 
-import static junit.framework.Assert.fail;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import org.junit.Test;
 
diff --git a/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
index 4004086..df9ddea 100644
--- a/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
+++ b/core/tests/coretests/src/android/app/timezone/RulesUpdaterContractTest.java
@@ -25,7 +25,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.UserHandle;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
diff --git a/core/tests/coretests/src/android/app/usage/EventListTest.java b/core/tests/coretests/src/android/app/usage/EventListTest.java
index 9dc0d43..685fcae 100644
--- a/core/tests/coretests/src/android/app/usage/EventListTest.java
+++ b/core/tests/coretests/src/android/app/usage/EventListTest.java
@@ -20,10 +20,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index 28aaf1e..1633e1a 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -21,6 +21,7 @@
 import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
 import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
 import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageEvents.Event.END_OF_DAY;
 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
@@ -33,8 +34,9 @@
 
 import android.app.usage.UsageEvents.Event;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -528,6 +530,11 @@
     }
 
     @Test
+    public void testEvent_DEVICE_SHUTDOWN() {
+        testClosingEvent(DEVICE_SHUTDOWN);
+    }
+
+    @Test
     public void testEvent_FLUSH_TO_DISK() {
         testClosingEvent(FLUSH_TO_DISK);
     }
@@ -535,8 +542,9 @@
     private void testClosingEvent(int eventType) {
         // When these three closing events are received, all open activities/services need to be
         // closed and usage stats are updated.
-        if (eventType != FLUSH_TO_DISK) {
-            fail("Closing eventType must be one of FLUSH_TO_DISK");
+        if (eventType != DEVICE_SHUTDOWN
+                && eventType != FLUSH_TO_DISK) {
+            fail("Closing eventType must be one of DEVICE_SHUTDOWN, FLUSH_TO_DISK");
         }
 
         left.mPackageName = "com.test";
diff --git a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
index 978ea7a..c307e64 100644
--- a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java
@@ -16,7 +16,6 @@
 
 package android.content;
 
-
 import static org.junit.Assert.fail;
 
 import android.app.ActivityManager;
@@ -30,9 +29,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/content/AssetTest.java b/core/tests/coretests/src/android/content/AssetTest.java
index b66574c..8e55e8a 100644
--- a/core/tests/coretests/src/android/content/AssetTest.java
+++ b/core/tests/coretests/src/android/content/AssetTest.java
@@ -18,7 +18,8 @@
 
 import android.content.res.AssetManager;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/core/tests/coretests/src/android/content/BrickDeniedTest.java b/core/tests/coretests/src/android/content/BrickDeniedTest.java
index 3d246b4..d8c9baa 100644
--- a/core/tests/coretests/src/android/content/BrickDeniedTest.java
+++ b/core/tests/coretests/src/android/content/BrickDeniedTest.java
@@ -17,7 +17,8 @@
 package android.content;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 /** Test to make sure brick intents <b>don't</b> work without permission. */
 public class BrickDeniedTest extends AndroidTestCase {
diff --git a/core/tests/coretests/src/android/content/BroadcastReceiverTests.java b/core/tests/coretests/src/android/content/BroadcastReceiverTests.java
index 8deccb7..1509ff9 100644
--- a/core/tests/coretests/src/android/content/BroadcastReceiverTests.java
+++ b/core/tests/coretests/src/android/content/BroadcastReceiverTests.java
@@ -18,9 +18,9 @@
 
 import static org.junit.Assert.fail;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/content/ContentProviderOperationTest.java b/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
index aea124b..b142761 100644
--- a/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
+++ b/core/tests/coretests/src/android/content/ContentProviderOperationTest.java
@@ -16,22 +16,23 @@
 
 package android.content;
 
-import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.net.Uri;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
+
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.util.HashMap;
-import java.util.Set;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 
 @SmallTest
 public class ContentProviderOperationTest extends TestCase {
diff --git a/core/tests/coretests/src/android/content/ContentProviderTest.java b/core/tests/coretests/src/android/content/ContentProviderTest.java
index 2142f27..8895f9b 100644
--- a/core/tests/coretests/src/android/content/ContentProviderTest.java
+++ b/core/tests/coretests/src/android/content/ContentProviderTest.java
@@ -23,7 +23,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ProviderInfo;
 import android.net.Uri;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/content/ContentQueryMapTest.java b/core/tests/coretests/src/android/content/ContentQueryMapTest.java
index f47bfdb..7106234 100644
--- a/core/tests/coretests/src/android/content/ContentQueryMapTest.java
+++ b/core/tests/coretests/src/android/content/ContentQueryMapTest.java
@@ -16,16 +16,14 @@
 
 package android.content;
 
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.database.Cursor;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 import java.util.Observable;
 import java.util.Observer;
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index 9940bf7..f14f289 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -31,10 +31,11 @@
 import android.net.Uri;
 import android.os.MemoryFile;
 import android.os.ParcelFileDescriptor;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Size;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/content/ContentValuesTest.java b/core/tests/coretests/src/android/content/ContentValuesTest.java
index 7b39939..0ab79e7 100644
--- a/core/tests/coretests/src/android/content/ContentValuesTest.java
+++ b/core/tests/coretests/src/android/content/ContentValuesTest.java
@@ -17,8 +17,8 @@
 package android.content;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 
+import androidx.test.filters.SmallTest;
 
 /*
   runtest -c android.content.ContentValuesTest frameworks-core
@@ -29,7 +29,7 @@
     adb shell pm uninstall -k com.android.frameworks.coretests && \
     adb install out/target/product/bullhead/testcases/FrameworksCoreTests/FrameworksCoreTests.apk && \
     adb shell am instrument -w -e package android.content \
-      com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+      com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
 */
 public class ContentValuesTest extends AndroidTestCase {
 
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index c8a3098..2f442c3 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -19,11 +19,12 @@
 import static org.junit.Assert.assertEquals;
 
 import android.app.ActivityThread;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowManager;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
index 4362ec3..22b2314 100644
--- a/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ManagedUserContentResolverTest.java
@@ -19,7 +19,8 @@
 import android.content.pm.UserInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 /**
  * To run the tests, use
@@ -32,7 +33,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class android.content.ManagedUserContentResolverTest -w \
- *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  */
 @LargeTest
 public class ManagedUserContentResolverTest extends AbstractCrossUserContentResolverTest {
diff --git a/core/tests/coretests/src/android/content/MemoryFileProviderTest.java b/core/tests/coretests/src/android/content/MemoryFileProviderTest.java
index bbe7c10..7cd4862 100644
--- a/core/tests/coretests/src/android/content/MemoryFileProviderTest.java
+++ b/core/tests/coretests/src/android/content/MemoryFileProviderTest.java
@@ -18,9 +18,10 @@
 
 import android.net.Uri;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
 
 import java.io.InputStream;
 import java.util.Arrays;
diff --git a/core/tests/coretests/src/android/content/RestrictionsManagerTest.java b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java
index 10d74f7..fd5de32 100644
--- a/core/tests/coretests/src/android/content/RestrictionsManagerTest.java
+++ b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
+
 package android.content;
 
 import android.os.Bundle;
 import android.os.Parcelable;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 
+import androidx.test.filters.LargeTest;
+
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
diff --git a/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java b/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java
index f8b13f0..dbe0278 100644
--- a/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/SecondaryUserContentResolverTest.java
@@ -18,7 +18,8 @@
 
 import android.content.pm.UserInfo;
 import android.os.RemoteException;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 /**
  * To run the tests, use
@@ -31,7 +32,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class android.content.SecondaryUserContentResolverTest -w \
- *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  */
 @LargeTest
 public class SecondaryUserContentResolverTest extends AbstractCrossUserContentResolverTest {
diff --git a/core/tests/coretests/src/android/content/UriMatcherTest.java b/core/tests/coretests/src/android/content/UriMatcherTest.java
index f3b9e76..6cef46b 100644
--- a/core/tests/coretests/src/android/content/UriMatcherTest.java
+++ b/core/tests/coretests/src/android/content/UriMatcherTest.java
@@ -17,14 +17,14 @@
 package android.content;
 
 import android.net.Uri;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 
-
 public class UriMatcherTest extends TestCase {
 
     static final int ROOT = 0;
diff --git a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
index 2acb08d..9b360db 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
@@ -20,7 +21,8 @@
 import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
 
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
index dce22ce..0ed76dc 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
 
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java
index 866de93..7f817d6 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
@@ -20,7 +21,8 @@
 import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
 
 import android.content.pm.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/ComponentTest.java b/core/tests/coretests/src/android/content/pm/ComponentTest.java
index cc75641..f31f0b5 100644
--- a/core/tests/coretests/src/android/content/pm/ComponentTest.java
+++ b/core/tests/coretests/src/android/content/pm/ComponentTest.java
@@ -21,7 +21,14 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.content.pm.PackageManager.GET_DISABLED_COMPONENTS;
 
-import android.test.suitebuilder.annotation.Suppress;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.test.AndroidTestCase;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+
 import com.android.frameworks.coretests.enabled_app.DisabledActivity;
 import com.android.frameworks.coretests.enabled_app.DisabledProvider;
 import com.android.frameworks.coretests.enabled_app.DisabledReceiver;
@@ -31,12 +38,6 @@
 import com.android.frameworks.coretests.enabled_app.EnabledReceiver;
 import com.android.frameworks.coretests.enabled_app.EnabledService;
 
-import android.content.ComponentName;
-import android.content.Intent;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-
 import java.util.List;
 
 /**
diff --git a/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
index 1f762fd..1c703ab 100644
--- a/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
+++ b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
@@ -17,7 +17,8 @@
 package android.content.pm;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
diff --git a/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java b/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java
index 659f9ea..1ddd753 100644
--- a/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java
+++ b/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java
@@ -16,9 +16,12 @@
 
 package android.content.pm;
 
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 
+import androidx.test.filters.LargeTest;
+
+import libcore.io.Streams;
+
 import java.io.ByteArrayInputStream;
 import java.util.Arrays;
 
@@ -26,8 +29,6 @@
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
-import libcore.io.Streams;
-
 @LargeTest
 public class MacAuthenticatedInputStreamTest extends AndroidTestCase {
 
diff --git a/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java b/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
index 91697c0..05db8ee 100644
--- a/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
+++ b/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import org.junit.Assume;
diff --git a/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java b/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java
index dcd2707..834a0bb 100644
--- a/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
 import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
index c64d520..3d7aab0 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
@@ -24,7 +24,8 @@
 
 import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Assume;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
index 4ceed83..c5db962 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBuilder.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static org.junit.Assert.assertEquals;
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 8ac9451d..0ab5367 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -54,11 +54,12 @@
 import android.system.Os;
 import android.system.StructStat;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+
 import com.android.frameworks.coretests.R;
 import com.android.internal.content.PackageHelper;
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserCacheHelperTest.java b/core/tests/coretests/src/android/content/pm/PackageParserCacheHelperTest.java
index 00be822..e852f98 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserCacheHelperTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserCacheHelperTest.java
@@ -22,8 +22,9 @@
 import android.content.pm.PackageParserCacheHelper.WriteHelper;
 import android.os.Bundle;
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 3f91a65..be1b1ce 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -29,9 +29,10 @@
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.SystemProperties;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java b/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java
index d5d3d7a..71a0e5e 100644
--- a/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import java.util.function.Supplier;
diff --git a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
index 952bb55..8874525 100644
--- a/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
+++ b/core/tests/coretests/src/android/content/pm/ParceledListSliceTest.java
@@ -1,8 +1,25 @@
+/*
+ * 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.
+ */
+
 package android.content.pm;
 
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index d3d1f22a..365e97d 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -21,11 +21,12 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.SparseArray;
 
+import androidx.test.filters.LargeTest;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
index 3dba440..216b0c8 100644
--- a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
+++ b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
@@ -20,7 +21,8 @@
 
 import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
index 15b27d7..fc60980 100644
--- a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
+++ b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.pm;
 
 import static android.content.pm.PackageBuilder.builder;
@@ -20,7 +21,8 @@
 
 import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
 import android.os.Build;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/content/pm/SignatureTest.java b/core/tests/coretests/src/android/content/pm/SignatureTest.java
index a3fa1a9..f0b4af6 100644
--- a/core/tests/coretests/src/android/content/pm/SignatureTest.java
+++ b/core/tests/coretests/src/android/content/pm/SignatureTest.java
@@ -16,7 +16,7 @@
 
 package android.content.pm;
 
-import android.support.test.filters.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
index 68942cb..f6527da 100644
--- a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
+++ b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
@@ -16,12 +16,12 @@
 
 package android.content.pm;
 
-import android.content.pm.VerificationParams;
 import android.net.Uri;
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 
+import androidx.test.filters.LargeTest;
+
 /**
  * Tests the android.content.pm.VerificationParams class
  *
diff --git a/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java b/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java
index 88d7a59..e7cd02d 100644
--- a/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java
+++ b/core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java
@@ -17,7 +17,8 @@
 package android.content.pm;
 
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import java.util.Random;
 
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
index e248a77..1ca879c 100644
--- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -29,12 +29,21 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
+import libcore.testing.io.TestIoUtils;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -45,14 +54,6 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
-import libcore.testing.io.TestIoUtils;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class DexMetadataHelperTest {
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index 47554a6..47b14bb 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -17,9 +17,10 @@
 package android.content.res;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.lang.reflect.InvocationTargetException;
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
index 72b9197..2fc3e36 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -13,19 +13,18 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package android.content.res;
 
-import org.junit.runner.RunWith;
-import org.junit.Test;
-import org.junit.runners.JUnit4;
-
-import android.content.res.Configuration;
-import android.support.test.filters.SmallTest;
 import android.platform.test.annotations.Presubmit;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
-import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 /**
  * Build/install/run: bit FrameworksCoreTests:android.content.res.ConfigurationTest
diff --git a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
index 42ff2e9..7ab9d7f 100644
--- a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
+++ b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.content.res;
 
 import static android.content.res.FontResourcesParser.FamilyResourceEntry;
@@ -26,9 +27,10 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.app.Instrumentation;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
index e85666e..aa1a534 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
@@ -13,14 +13,15 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package android.content.res;
 
 import android.os.FileUtils;
 import android.os.LocaleList;
-import android.support.test.filters.SmallTest;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
-import android.view.Display;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index b2ff927..a2dab99 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -13,18 +13,20 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package android.content.res;
 
 import android.annotation.NonNull;
 import android.app.ResourcesManager;
 import android.os.Binder;
 import android.os.LocaleList;
-import android.support.test.filters.SmallTest;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.DisplayAdjustments;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 public class ResourcesManagerTest extends TestCase {
diff --git a/core/tests/coretests/src/android/database/CursorWindowTest.java b/core/tests/coretests/src/android/database/CursorWindowTest.java
index 075f5b7..123da3e 100644
--- a/core/tests/coretests/src/android/database/CursorWindowTest.java
+++ b/core/tests/coretests/src/android/database/CursorWindowTest.java
@@ -16,14 +16,14 @@
 
 package android.database;
 
-import android.test.suitebuilder.annotation.SmallTest;
-import android.database.CursorWindow;
 import android.test.PerformanceTestCase;
 
-import java.util.Arrays;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
+import java.util.Arrays;
+
 public class CursorWindowTest extends TestCase implements PerformanceTestCase {
     public boolean isPerformanceOnly() {
         return false;
diff --git a/core/tests/coretests/src/android/database/DatabaseCursorTest.java b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
index 3507223..eb4fd70 100644
--- a/core/tests/coretests/src/android/database/DatabaseCursorTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
@@ -18,10 +18,6 @@
 
 import android.content.ContentValues;
 import android.content.Context;
-import android.database.Cursor;
-import android.database.CursorIndexOutOfBoundsException;
-import android.database.DataSetObserver;
-import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteCursor;
 import android.database.sqlite.SQLiteCursorDriver;
 import android.database.sqlite.SQLiteDatabase;
@@ -29,11 +25,12 @@
 import android.os.Looper;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
index 9d75c78..49fb75b 100644
--- a/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseGeneralTest.java
@@ -25,16 +25,17 @@
 import android.database.sqlite.SQLiteDebug;
 import android.database.sqlite.SQLiteException;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.Assert;
 
 import java.io.File;
diff --git a/core/tests/coretests/src/android/database/DatabaseLocaleTest.java b/core/tests/coretests/src/android/database/DatabaseLocaleTest.java
index b3282941..ee7936f 100644
--- a/core/tests/coretests/src/android/database/DatabaseLocaleTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseLocaleTest.java
@@ -17,17 +17,17 @@
 package android.database;
 
 import android.database.sqlite.SQLiteDatabase;
-import android.database.Cursor;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 import android.test.MoreAsserts;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
+import junit.framework.TestCase;
 
 import java.util.ArrayList;
 import java.util.Locale;
 
-import junit.framework.TestCase;
-
 public class DatabaseLocaleTest extends TestCase {
 
     private SQLiteDatabase mDatabase;
diff --git a/core/tests/coretests/src/android/database/DatabaseLockTest.java b/core/tests/coretests/src/android/database/DatabaseLockTest.java
index 8d3cf5a..e8936c9 100644
--- a/core/tests/coretests/src/android/database/DatabaseLockTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseLockTest.java
@@ -17,11 +17,13 @@
 package android.database;
 
 import android.database.sqlite.SQLiteDatabase;
-import android.test.suitebuilder.annotation.Suppress;
+import android.test.AndroidTestCase;
 import android.util.Log;
+
+import androidx.test.filters.Suppress;
+
 import java.io.File;
 import java.util.concurrent.atomic.AtomicInteger;
-import android.test.AndroidTestCase;
 
 /* 
  * This is a series of unit tests for database locks.
diff --git a/core/tests/coretests/src/android/database/DatabaseStatementTest.java b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
index 895d715..4b34650 100644
--- a/core/tests/coretests/src/android/database/DatabaseStatementTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
@@ -17,14 +17,14 @@
 package android.database;
 
 import android.content.Context;
-import android.database.Cursor;
 import android.database.sqlite.SQLiteConstraintException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDoneException;
 import android.database.sqlite.SQLiteStatement;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
 
 import java.io.File;
 
diff --git a/core/tests/coretests/src/android/database/DatabaseStressTest.java b/core/tests/coretests/src/android/database/DatabaseStressTest.java
index 30e46e7..bfea1fc 100644
--- a/core/tests/coretests/src/android/database/DatabaseStressTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseStressTest.java
@@ -17,11 +17,11 @@
 package android.database;
 
 import android.content.Context;
-import android.database.sqlite.*;
+import android.database.sqlite.SQLiteDatabase;
+import android.test.AndroidTestCase;
 import android.util.Log;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.Suppress;
+import androidx.test.filters.Suppress;
 
 import java.io.File;
 
diff --git a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
index 7c206d7..be156c8 100644
--- a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
@@ -20,7 +20,7 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/database/RedactingCursorTest.java b/core/tests/coretests/src/android/database/RedactingCursorTest.java
index 93998f3..e2d2bae 100644
--- a/core/tests/coretests/src/android/database/RedactingCursorTest.java
+++ b/core/tests/coretests/src/android/database/RedactingCursorTest.java
@@ -22,8 +22,9 @@
 
 import android.content.Context;
 import android.net.Uri;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java b/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java
index 9ed3f11b..730a3cb 100644
--- a/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java
+++ b/core/tests/coretests/src/android/database/SQLiteOpenHelperTest.java
@@ -26,11 +26,12 @@
 import android.database.sqlite.SQLiteDatabaseConfiguration;
 import android.database.sqlite.SQLiteDebug;
 import android.database.sqlite.SQLiteOpenHelper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/database/run_newdb_perf_test.sh b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
index c5b2c97..95f1f83 100755
--- a/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
+++ b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
@@ -23,7 +23,7 @@
 
 for (( i=0; i<$RUN_N; i++ ))
 do
-    adb  shell am instrument -e class 'android.database.NewDatabasePerformanceTestSuite' -w 'com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner'
+    adb  shell am instrument -e class 'android.database.NewDatabasePerformanceTestSuite' -w 'com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner'
 done
 
 adb logcat -d > /tmp/testlogcat.txt
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
index 551a58e..5dbcb3c 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCompatibilityWalFlagsTest.java
@@ -22,9 +22,10 @@
 
 import android.content.Context;
 import android.database.DatabaseUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java
index ed14a53..f1d27d4 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java
@@ -21,11 +21,12 @@
 
 import android.content.Context;
 import android.os.HandlerThread;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
index c52cf6e..78d3c41 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteCursorTest.java
@@ -23,7 +23,8 @@
 import android.database.CursorWindow;
 import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import java.io.File;
 import java.util.Arrays;
diff --git a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
index e9e2a4d..564460e 100644
--- a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
@@ -17,14 +17,14 @@
 package android.graphics;
 
 import android.os.ParcelFileDescriptor;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
 
-
 public class BitmapFactoryTest extends TestCase {
 
     // tests that we can decode bitmaps from MemoryFiles
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index 3666ddd..e79d2ae 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -16,11 +16,10 @@
 
 package android.graphics;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
-
 public class BitmapTest extends TestCase {
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/graphics/ColorSpaceRendererTest.java b/core/tests/coretests/src/android/graphics/ColorSpaceRendererTest.java
index 6e38fb6..8e9b38c 100644
--- a/core/tests/coretests/src/android/graphics/ColorSpaceRendererTest.java
+++ b/core/tests/coretests/src/android/graphics/ColorSpaceRendererTest.java
@@ -19,8 +19,8 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/graphics/ColorStateListTest.java b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
index 374d142..1d34f938 100644
--- a/core/tests/coretests/src/android/graphics/ColorStateListTest.java
+++ b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
@@ -19,7 +19,8 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
index 76267b2..1771671 100644
--- a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
+++ b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
@@ -22,11 +22,12 @@
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontFileUtil;
 import android.graphics.fonts.FontVariationAxis;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import org.junit.Test;
 
 import java.io.File;
diff --git a/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java b/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
index 164c1aa..3cfeb25 100644
--- a/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
+++ b/core/tests/coretests/src/android/graphics/GraphicsPerformanceTests.java
@@ -20,7 +20,8 @@
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.Suppress;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index b5ed01f..bf56df1 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -18,9 +18,9 @@
 
 import static org.junit.Assert.assertNotEquals;
 
-import android.graphics.Paint;
 import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import java.util.Arrays;
 import java.util.HashSet;
diff --git a/core/tests/coretests/src/android/graphics/PathOffsetTest.java b/core/tests/coretests/src/android/graphics/PathOffsetTest.java
index 950f873..6cc42f6 100644
--- a/core/tests/coretests/src/android/graphics/PathOffsetTest.java
+++ b/core/tests/coretests/src/android/graphics/PathOffsetTest.java
@@ -16,13 +16,13 @@
 
 package android.graphics;
 
+import static org.junit.Assert.assertTrue;
 
 import android.graphics.Bitmap.Config;
 import android.graphics.Path.Direction;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 
-import static org.junit.Assert.assertTrue;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/graphics/PathTest.java b/core/tests/coretests/src/android/graphics/PathTest.java
index 78e4959..c6d6d1f 100644
--- a/core/tests/coretests/src/android/graphics/PathTest.java
+++ b/core/tests/coretests/src/android/graphics/PathTest.java
@@ -16,11 +16,10 @@
 
 package android.graphics;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
-
 public class PathTest extends TestCase {
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/graphics/RectTest.java b/core/tests/coretests/src/android/graphics/RectTest.java
index d31d7d5..2918f44 100644
--- a/core/tests/coretests/src/android/graphics/RectTest.java
+++ b/core/tests/coretests/src/android/graphics/RectTest.java
@@ -23,8 +23,9 @@
 import static org.junit.Assert.assertNull;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
index 909a8d9..e1ca7df 100644
--- a/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import android.test.suitebuilder.annotation.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 6fdb71f..c66bac6 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -27,12 +27,13 @@
 import android.graphics.fonts.FontCustomizationParser;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.FontConfig;
 import android.util.ArrayMap;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/graphics/TypefaceTest.java b/core/tests/coretests/src/android/graphics/TypefaceTest.java
index b0c7976..2d16f82 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceTest.java
@@ -22,13 +22,12 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
-import android.graphics.Paint;
-import android.graphics.Typeface;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
index 781e343..3dc9987 100644
--- a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package android.graphics.drawable;
 
 import android.content.res.Resources;
@@ -11,11 +27,12 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import android.util.PathParser;
 
+import androidx.test.filters.LargeTest;
+
 import org.junit.Test;
 
 import java.io.File;
diff --git a/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java b/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java
index 655efb5..d0a6ff9 100644
--- a/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/DrawableWrapperTest.java
@@ -24,8 +24,9 @@
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Xfermode;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index 64fadc0..2bdcc28 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -25,9 +25,10 @@
 import android.os.HandlerThread;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.io.ByteArrayOutputStream;
diff --git a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
index f90ae34..0a25bd7 100644
--- a/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
+++ b/core/tests/coretests/src/android/hardware/display/AmbientBrightnessDayStatsTest.java
@@ -23,8 +23,9 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index dcc51e1..823fca5 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -22,10 +22,11 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
index f30b1a2..daf6139 100644
--- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
+++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
@@ -22,15 +22,12 @@
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.drawable.ColorDrawable;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.VirtualDisplay;
 import android.media.Image;
 import android.media.ImageReader;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -40,6 +37,8 @@
 import android.view.WindowManager;
 import android.widget.ImageView;
 
+import androidx.test.filters.LargeTest;
+
 import java.nio.ByteBuffer;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
diff --git a/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java
new file mode 100644
index 0000000..16be0b0
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.hdmi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiUtils} class. */
+public class HdmiUtilsTest {
+
+    @Test
+    public void pathToPort_isMe() {
+        int targetPhysicalAddress = 0x1000;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                HdmiUtils.TARGET_SAME_PHYSICAL_ADDRESS);
+    }
+
+    @Test
+    public void pathToPort_isDirectlyBelow() {
+        int targetPhysicalAddress = 0x1100;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+            targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
+    }
+
+    @Test
+    public void pathToPort_isBelow() {
+        int targetPhysicalAddress = 0x1110;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+            targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
+    }
+
+    @Test
+    public void pathToPort_neitherMeNorBelow() {
+        int targetPhysicalAddress = 0x3000;
+        int myPhysicalAddress = 0x2000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2200;
+        myPhysicalAddress = 0x3300;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2213;
+        myPhysicalAddress = 0x2212;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2340;
+        myPhysicalAddress = 0x2310;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+    }
+}
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index 3be776d..aabfc28 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -13,9 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.metrics;
 
-import android.support.test.filters.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
index 784a12f..96dac64 100644
--- a/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
+++ b/core/tests/coretests/src/android/metrics/MetricsReaderTest.java
@@ -13,10 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.metrics;
 
 import android.metrics.MetricsReader.Event;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/core/tests/coretests/src/android/net/LocalSocketTest.java b/core/tests/coretests/src/android/net/LocalSocketTest.java
index 1286b13..9172237 100644
--- a/core/tests/coretests/src/android/net/LocalSocketTest.java
+++ b/core/tests/coretests/src/android/net/LocalSocketTest.java
@@ -16,12 +16,9 @@
 
 package android.net;
 
-import android.net.Credentials;
-import android.net.LocalServerSocket;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
 import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java
index fff23a0..0f1c71d 100644
--- a/core/tests/coretests/src/android/net/NetworkKeyTest.java
+++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 package android.net;
 
 import static org.junit.Assert.assertEquals;
@@ -7,7 +23,8 @@
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiSsid;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java b/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java
index c6758ce..29e212f 100644
--- a/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkPolicyManagerTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.net;
 
 import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
diff --git a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
index ff9816a..3e45a79 100644
--- a/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
+++ b/core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
 package android.net;
 
 import static junit.framework.Assert.assertFalse;
@@ -9,7 +25,8 @@
 
 import android.Manifest.permission;
 import android.content.Context;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java b/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java
index 5cbf02a..bc12e72 100644
--- a/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java
+++ b/core/tests/coretests/src/android/net/SSLCertificateSocketFactoryTest.java
@@ -19,7 +19,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
index 11d066b..eec09e6 100644
--- a/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
+++ b/core/tests/coretests/src/android/net/SSLSessionCacheTest.java
@@ -19,10 +19,10 @@
 import com.android.org.conscrypt.ClientSessionContext;
 import com.android.org.conscrypt.SSLClientSessionCache;
 
-import org.mockito.Mockito;
-
 import junit.framework.TestCase;
 
+import org.mockito.Mockito;
+
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
 
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
index 109f32e..d984d86 100644
--- a/core/tests/coretests/src/android/net/ScoredNetworkTest.java
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -16,11 +16,17 @@
 
 package android.net;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.os.Bundle;
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java
index d72738c..87edb6e 100644
--- a/core/tests/coretests/src/android/net/SntpClientTest.java
+++ b/core/tests/coretests/src/android/net/SntpClientTest.java
@@ -20,9 +20,10 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import libcore.util.HexEncoding;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index ea0347d..a33de7b 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -18,7 +18,8 @@
 
 import android.content.ContentUris;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/net/WebAddressTest.java b/core/tests/coretests/src/android/net/WebAddressTest.java
index 6fcb97e..70a6253 100644
--- a/core/tests/coretests/src/android/net/WebAddressTest.java
+++ b/core/tests/coretests/src/android/net/WebAddressTest.java
@@ -16,8 +16,8 @@
 
 package android.net;
 
-import android.net.WebAddress;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 public class WebAddressTest extends TestCase {
diff --git a/core/tests/coretests/src/android/net/http/SslCertificateTest.java b/core/tests/coretests/src/android/net/http/SslCertificateTest.java
index 6a30c6c..1beb1de 100644
--- a/core/tests/coretests/src/android/net/http/SslCertificateTest.java
+++ b/core/tests/coretests/src/android/net/http/SslCertificateTest.java
@@ -17,12 +17,13 @@
 
 package android.net.http;
 
-import android.net.http.SslCertificate;
-import android.test.suitebuilder.annotation.LargeTest;
+import androidx.test.filters.LargeTest;
+
+import junit.framework.TestCase;
+
 import java.io.ByteArrayInputStream;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import junit.framework.TestCase;
 
 public class SslCertificateTest extends TestCase {
 
diff --git a/core/tests/coretests/src/android/os/AidlTest.java b/core/tests/coretests/src/android/os/AidlTest.java
index bf11d56..4c51415 100644
--- a/core/tests/coretests/src/android/os/AidlTest.java
+++ b/core/tests/coretests/src/android/os/AidlTest.java
@@ -16,11 +16,10 @@
 
 package android.os;
 
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+
 import com.google.android.collect.Lists;
+
 import junit.framework.TestCase;
 
 import java.util.List;
diff --git a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
index 6cdb35ab..ce6ad87 100644
--- a/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyCountingTest.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package android.os;
 
 import static org.junit.Assert.assertEquals;
@@ -25,12 +24,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.aidl.IBpcCallbackObserver;
 import com.android.frameworks.coretests.aidl.IBpcTestAppCmdService;
 import com.android.frameworks.coretests.aidl.IBpcTestServiceCmdService;
@@ -63,7 +63,7 @@
  * Install: adb install -r \
  * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class android.os.BinderProxyCountingTest -w \
- * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  *
  * or
  *
diff --git a/core/tests/coretests/src/android/os/BinderProxyTest.java b/core/tests/coretests/src/android/os/BinderProxyTest.java
index 4c36b5c..aceda2d 100644
--- a/core/tests/coretests/src/android/os/BinderProxyTest.java
+++ b/core/tests/coretests/src/android/os/BinderProxyTest.java
@@ -19,7 +19,8 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
 
 public class BinderProxyTest extends AndroidTestCase {
     private static class CountingListener implements Binder.ProxyTransactListener {
diff --git a/core/tests/coretests/src/android/os/BinderTest.java b/core/tests/coretests/src/android/os/BinderTest.java
index 6c9c3c1..a354195 100644
--- a/core/tests/coretests/src/android/os/BinderTest.java
+++ b/core/tests/coretests/src/android/os/BinderTest.java
@@ -16,7 +16,7 @@
 
 package android.os;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityService.java b/core/tests/coretests/src/android/os/BinderThreadPriorityService.java
index 47a4483..ed42058 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityService.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityService.java
@@ -18,7 +18,6 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.text.TextUtils;
 import android.util.Log;
 
 /**
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
index 56e977c..48c9df6 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
@@ -21,7 +21,6 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
 
 import java.io.File;
diff --git a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
index 5664df6..e16a3db 100644
--- a/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
+++ b/core/tests/coretests/src/android/os/BinderWorkSourceTest.java
@@ -24,9 +24,10 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index fabcf3d..5a3724f 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.hardware.display.DisplayManager;
-import android.os.Bundle;
 import android.provider.Settings;
 import android.view.View;
 import android.view.View.OnClickListener;
diff --git a/core/tests/coretests/src/android/os/BroadcasterTest.java b/core/tests/coretests/src/android/os/BroadcasterTest.java
index 551ea8d..b4c47af9 100644
--- a/core/tests/coretests/src/android/os/BroadcasterTest.java
+++ b/core/tests/coretests/src/android/os/BroadcasterTest.java
@@ -16,11 +16,8 @@
 
 package android.os;
 
-import android.os.Broadcaster;
-import android.os.Handler;
-import android.os.Message;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.MediumTest;
+
 import junit.framework.TestCase;
 
 public class BroadcasterTest extends TestCase {
diff --git a/core/tests/coretests/src/android/os/BuildTest.java b/core/tests/coretests/src/android/os/BuildTest.java
index 3758627..decc768 100644
--- a/core/tests/coretests/src/android/os/BuildTest.java
+++ b/core/tests/coretests/src/android/os/BuildTest.java
@@ -16,9 +16,8 @@
 
 package android.os;
 
-import android.os.Build;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java
index 9fcf96d..e4dc993 100644
--- a/core/tests/coretests/src/android/os/BundleTest.java
+++ b/core/tests/coretests/src/android/os/BundleTest.java
@@ -20,8 +20,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/os/EnvironmentTest.java b/core/tests/coretests/src/android/os/EnvironmentTest.java
index 5189df5..d98ceaf 100644
--- a/core/tests/coretests/src/android/os/EnvironmentTest.java
+++ b/core/tests/coretests/src/android/os/EnvironmentTest.java
@@ -25,8 +25,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/os/FileObserverTest.java b/core/tests/coretests/src/android/os/FileObserverTest.java
index 93e27af..ece7645 100644
--- a/core/tests/coretests/src/android/os/FileObserverTest.java
+++ b/core/tests/coretests/src/android/os/FileObserverTest.java
@@ -16,13 +16,14 @@
 
 package android.os;
 
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.Iterator;
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 514ea0c..5bce227c 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -51,8 +51,9 @@
 import android.content.Context;
 import android.os.FileUtils.MemoryPipe;
 import android.provider.DocumentsContract.Document;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.io.Streams;
 
diff --git a/core/tests/coretests/src/android/os/HandlerTester.java b/core/tests/coretests/src/android/os/HandlerTester.java
index a216a0b..fa442f4 100644
--- a/core/tests/coretests/src/android/os/HandlerTester.java
+++ b/core/tests/coretests/src/android/os/HandlerTester.java
@@ -16,10 +16,6 @@
 
 package android.os;
 
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
 public abstract class HandlerTester extends Thread {
     public abstract void go();
     public abstract void handleMessage(Message msg);
diff --git a/core/tests/coretests/src/android/os/HandlerThreadTest.java b/core/tests/coretests/src/android/os/HandlerThreadTest.java
index 9772aa4..93cfc40 100644
--- a/core/tests/coretests/src/android/os/HandlerThreadTest.java
+++ b/core/tests/coretests/src/android/os/HandlerThreadTest.java
@@ -16,13 +16,9 @@
 
 package android.os;
 
+import androidx.test.filters.MediumTest;
+
 import junit.framework.TestCase;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Message;
-import android.os.Process;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
 
 public class HandlerThreadTest extends TestCase {
     private static final int TEST_WHAT = 1;
diff --git a/core/tests/coretests/src/android/os/IdleHandlerTest.java b/core/tests/coretests/src/android/os/IdleHandlerTest.java
index 6c0a862..d8886c9 100644
--- a/core/tests/coretests/src/android/os/IdleHandlerTest.java
+++ b/core/tests/coretests/src/android/os/IdleHandlerTest.java
@@ -16,11 +16,10 @@
 
 package android.os;
 
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
 import android.os.MessageQueue.IdleHandler;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
+
 import junit.framework.TestCase;
 
 public class IdleHandlerTest extends TestCase {
diff --git a/core/tests/coretests/src/android/os/LocaleListTest.java b/core/tests/coretests/src/android/os/LocaleListTest.java
index 17ef773..1f00a7a 100644
--- a/core/tests/coretests/src/android/os/LocaleListTest.java
+++ b/core/tests/coretests/src/android/os/LocaleListTest.java
@@ -13,14 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.os;
 
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.Locale;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
+import java.util.Locale;
+
 public class LocaleListTest extends TestCase {
     @SmallTest
     public void testConstructor() throws Exception {
diff --git a/core/tests/coretests/src/android/os/MemoryFileTest.java b/core/tests/coretests/src/android/os/MemoryFileTest.java
index 20b298d..05c2995 100644
--- a/core/tests/coretests/src/android/os/MemoryFileTest.java
+++ b/core/tests/coretests/src/android/os/MemoryFileTest.java
@@ -17,8 +17,9 @@
 package android.os;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SmallTest;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/core/tests/coretests/src/android/os/MessageQueueTest.java b/core/tests/coretests/src/android/os/MessageQueueTest.java
index 1cd1020..2c5588e 100644
--- a/core/tests/coretests/src/android/os/MessageQueueTest.java
+++ b/core/tests/coretests/src/android/os/MessageQueueTest.java
@@ -16,11 +16,9 @@
 
 package android.os;
 
-import android.os.Handler;
-import android.os.Message;
-import android.os.SystemClock;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 import junit.framework.TestCase;
 
 @Suppress  // Failing.
diff --git a/core/tests/coretests/src/android/os/MessengerService.java b/core/tests/coretests/src/android/os/MessengerService.java
index f15e134..db33471 100644
--- a/core/tests/coretests/src/android/os/MessengerService.java
+++ b/core/tests/coretests/src/android/os/MessengerService.java
@@ -18,11 +18,6 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.os.RemoteException;
-import android.os.IBinder;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
 
 public class MessengerService extends Service {
     private final Handler mHandler = new Handler() {
diff --git a/core/tests/coretests/src/android/os/MessengerTest.java b/core/tests/coretests/src/android/os/MessengerTest.java
index 473ffe2..9143ff1 100644
--- a/core/tests/coretests/src/android/os/MessengerTest.java
+++ b/core/tests/coretests/src/android/os/MessengerTest.java
@@ -20,13 +20,9 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.RemoteException;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
 
 public class MessengerTest extends AndroidTestCase {
     private Messenger mServiceMessenger;
diff --git a/core/tests/coretests/src/android/os/OsTests.java b/core/tests/coretests/src/android/os/OsTests.java
index 2b84126..08fb945 100644
--- a/core/tests/coretests/src/android/os/OsTests.java
+++ b/core/tests/coretests/src/android/os/OsTests.java
@@ -16,12 +16,8 @@
 
 package android.os;
 
-import com.google.android.collect.Lists;
 import junit.framework.TestSuite;
 
-import java.util.Enumeration;
-import java.util.List;
-
 public class OsTests {
     public static TestSuite suite() {
         TestSuite suite = new TestSuite(OsTests.class.getName());
diff --git a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
index 516dc0a..a6b296d 100644
--- a/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
+++ b/core/tests/coretests/src/android/os/ParcelNullabilityTest.java
@@ -20,10 +20,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/os/PatternMatcherTest.java b/core/tests/coretests/src/android/os/PatternMatcherTest.java
index 9645ccc..82350cd 100644
--- a/core/tests/coretests/src/android/os/PatternMatcherTest.java
+++ b/core/tests/coretests/src/android/os/PatternMatcherTest.java
@@ -1,9 +1,27 @@
+/*
+ * 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.
+ */
+
 package android.os;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
-import org.junit.runner.RunWith;
+
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
diff --git a/core/tests/coretests/src/android/os/PerformanceCollectorTest.java b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
index 7533c84..38ad90f 100644
--- a/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
+++ b/core/tests/coretests/src/android/os/PerformanceCollectorTest.java
@@ -17,15 +17,16 @@
 package android.os;
 
 import android.os.PerformanceCollector.PerformanceResultsWriter;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
+import junit.framework.TestCase;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Random;
 
-import junit.framework.TestCase;
-
 public class PerformanceCollectorTest extends TestCase {
 
     private PerformanceCollector mPerfCollector;
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index a828f44..1b587dd 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -21,10 +21,11 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 
 import org.junit.After;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/os/PowerManagerVrTest.java b/core/tests/coretests/src/android/os/PowerManagerVrTest.java
index e01e5fa..5d2c65b 100644
--- a/core/tests/coretests/src/android/os/PowerManagerVrTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerVrTest.java
@@ -19,16 +19,14 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.provider.Settings;
-import android.service.dreams.IDreamManager;
 import android.service.dreams.DreamService;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
+import android.service.dreams.IDreamManager;
 import android.test.ActivityInstrumentationTestCase2;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests dream aspects of PowerManager.
  */
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index 1f5b7c8..b749e71 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -17,14 +17,10 @@
 
 package android.os;
 
-import android.os.Process;
-import android.os.UserHandle;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.MediumTest;
 
 import junit.framework.TestCase;
 
-
 public class ProcessTest extends TestCase {
 
     @MediumTest
diff --git a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
index 9e15231..d5163e1 100644
--- a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
+++ b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
@@ -24,10 +24,11 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.system.Os;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
index 9e44554..8085993 100644
--- a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
+++ b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.os;
 
 import android.app.ActivityManager;
@@ -20,10 +21,10 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.os.Process;
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 /**
  * Tests ActivityManager#setPersistentVrThread and ActivityManager#setVrThread's
diff --git a/core/tests/coretests/src/android/os/TestHandlerThread.java b/core/tests/coretests/src/android/os/TestHandlerThread.java
index 7e84af3..8c0330b 100644
--- a/core/tests/coretests/src/android/os/TestHandlerThread.java
+++ b/core/tests/coretests/src/android/os/TestHandlerThread.java
@@ -16,11 +16,6 @@
 
 package android.os;
 
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.MessageQueue.IdleHandler;
-
 abstract class TestHandlerThread {
     private boolean mDone = false;
     private boolean mSuccess = false;
diff --git a/core/tests/coretests/src/android/os/TestVrActivity.java b/core/tests/coretests/src/android/os/TestVrActivity.java
index 33ff164..75df7c2 100644
--- a/core/tests/coretests/src/android/os/TestVrActivity.java
+++ b/core/tests/coretests/src/android/os/TestVrActivity.java
@@ -17,7 +17,6 @@
 package android.os;
 
 import android.app.Activity;
-import android.os.Bundle;
 import android.service.vr.VrListenerService;
 
 import java.util.concurrent.CountDownLatch;
diff --git a/core/tests/coretests/src/android/os/TraceTest.java b/core/tests/coretests/src/android/os/TraceTest.java
index 1541553..5cad549 100644
--- a/core/tests/coretests/src/android/os/TraceTest.java
+++ b/core/tests/coretests/src/android/os/TraceTest.java
@@ -16,13 +16,13 @@
 
 package android.os;
 
-import android.os.Debug;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+
 /**
  * This class is used to test the native tracing support.  Run this test
  * while tracing on the emulator and then run traceview to view the trace.
diff --git a/core/tests/coretests/src/android/os/UserHandleTest.java b/core/tests/coretests/src/android/os/UserHandleTest.java
index af559fd..4a1cdbf 100644
--- a/core/tests/coretests/src/android/os/UserHandleTest.java
+++ b/core/tests/coretests/src/android/os/UserHandleTest.java
@@ -25,7 +25,7 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
index 44510c2..af3660a 100644
--- a/core/tests/coretests/src/android/os/VintfObjectTest.java
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -16,7 +16,6 @@
 
 package android.os;
 
-import junit.framework.Assert;
 import junit.framework.TestCase;
 
 public class VintfObjectTest extends TestCase {
diff --git a/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
index 3ec297c..62f2ac2 100644
--- a/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java
@@ -19,7 +19,8 @@
 import android.os.ParcelFileDescriptor;
 import android.os.ProxyFileDescriptorCallback;
 import android.system.ErrnoException;
-import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/preference/ListPreferenceTest.java b/core/tests/coretests/src/android/preference/ListPreferenceTest.java
index 72f62f1..51dbb64 100644
--- a/core/tests/coretests/src/android/preference/ListPreferenceTest.java
+++ b/core/tests/coretests/src/android/preference/ListPreferenceTest.java
@@ -16,10 +16,10 @@
 
 package android.preference;
 
-import android.preference.ListPreference;
-import android.support.test.filters.LargeTest;
 import android.test.AndroidTestCase;
 
+import androidx.test.filters.LargeTest;
+
 @LargeTest
 public class ListPreferenceTest extends AndroidTestCase {
     public void testListPreferenceSummaryFromEntries() {
diff --git a/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java
index 654474c..0deb77e 100644
--- a/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java
+++ b/core/tests/coretests/src/android/preference/PreferenceIconSpaceTest.java
@@ -16,20 +16,20 @@
 
 package android.preference;
 
-
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
index 5d12f7e..94d85e6 100644
--- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
+++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java
@@ -41,9 +41,10 @@
 import android.print.test.services.PrinterDiscoverySessionCallbacks;
 import android.print.test.services.StubbablePrinterDiscoverySession;
 import android.printservice.recommendation.IRecommendationsChangeListener;
-import android.support.test.filters.LargeTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 800b864..17e9654 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -28,9 +28,10 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
index 1465d0a9..02a9adf 100644
--- a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
@@ -20,9 +20,10 @@
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.provider.DocumentsContract.Path;
-import android.support.test.filters.SmallTest;
 import android.test.ProviderTestCase2;
 
+import androidx.test.filters.SmallTest;
+
 import java.util.Arrays;
 
 /**
diff --git a/core/tests/coretests/src/android/provider/FontsContractE2ETest.java b/core/tests/coretests/src/android/provider/FontsContractE2ETest.java
index 2955869..7e02be8 100644
--- a/core/tests/coretests/src/android/provider/FontsContractE2ETest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractE2ETest.java
@@ -25,25 +25,25 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
 import android.graphics.Typeface;
 import android.os.Handler;
-import android.provider.FontsContract.Columns;
 import android.provider.FontsContract.FontFamilyResult;
-import android.provider.FontsContract.FontInfo;
-import android.provider.FontsContract;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import java.util.ArrayList;
-import java.util.List;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class FontsContractE2ETest {
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index d42d79e..c5d6f7f 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -13,31 +13,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.provider;
 
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
+import static android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
+import static android.provider.FontsContract.Columns.RESULT_CODE_OK;
+
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import static android.provider.FontsContract.Columns.RESULT_CODE_OK;
-import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
-import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
-import static android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
-
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ProviderInfo;
 import android.content.pm.Signature;
 import android.database.MatrixCursor;
 import android.graphics.fonts.FontVariationAxis;
 import android.provider.FontsContract.FontInfo;
-import android.support.test.filters.SmallTest;
 import android.test.ProviderTestCase2;
 import android.util.Base64;
 
+import androidx.test.filters.SmallTest;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
diff --git a/core/tests/coretests/src/android/provider/MockFontProvider.java b/core/tests/coretests/src/android/provider/MockFontProvider.java
index ad5b130..e527dec 100644
--- a/core/tests/coretests/src/android/provider/MockFontProvider.java
+++ b/core/tests/coretests/src/android/provider/MockFontProvider.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.provider;
 
 import static android.provider.FontsContract.Columns;
@@ -21,16 +22,13 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.database.Cursor;
 import android.database.MatrixCursor;
-import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
-import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
-import android.util.ArraySet;
-import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -46,8 +44,6 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
-import com.android.internal.annotations.GuardedBy;
-
 public class MockFontProvider extends ContentProvider {
     final static String AUTHORITY = "android.provider.fonts.font";
 
diff --git a/core/tests/coretests/src/android/provider/SearchRecentSuggestionsProviderTest.java b/core/tests/coretests/src/android/provider/SearchRecentSuggestionsProviderTest.java
index 7458de5..f84355f 100644
--- a/core/tests/coretests/src/android/provider/SearchRecentSuggestionsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SearchRecentSuggestionsProviderTest.java
@@ -21,9 +21,9 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.test.ProviderTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 /**
  * ProviderTestCase that performs unit tests of SearchRecentSuggestionsProvider.
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 1ed5ce4..93af013 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -27,9 +27,9 @@
 import static java.lang.reflect.Modifier.isStatic;
 
 import android.platform.test.annotations.Presubmit;
-import android.provider.Settings.Global;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -270,6 +270,7 @@
                     Settings.Global.GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS,
                     Settings.Global.GNSS_SATELLITE_BLACKLIST,
                     Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
+                    Settings.Global.HDMI_CEC_SWITCH_ENABLED,
                     Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                     Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
                     Settings.Global.HDMI_CONTROL_ENABLED,
@@ -477,9 +478,10 @@
                     Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
                     Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
                     Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
+                    Settings.Global.GUP_DEV_ALL_APPS,
                     Settings.Global.GUP_DEV_OPT_IN_APPS,
                     Settings.Global.GUP_DEV_OPT_OUT_APPS,
-                    Settings.Global.GUP_BLACK_LIST,
+                    Settings.Global.GUP_BLACKLIST,
                     Settings.Global.GPU_DEBUG_LAYER_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
@@ -554,8 +556,10 @@
                     Settings.Global.APPOP_HISTORY_PARAMETERS,
                     Settings.Global.APPOP_HISTORY_MODE,
                     Settings.Global.APPOP_HISTORY_INTERVAL_MULTIPLIER,
-                    Settings.Global.APPOP_HISTORY_BASE_INTERVAL_MILLIS);
-
+                    Settings.Global.APPOP_HISTORY_BASE_INTERVAL_MILLIS,
+                    Settings.Global.ENABLE_RADIO_BUG_DETECTION,
+                    Settings.Global.RADIO_BUG_WAKELOCK_TIMEOUT_COUNT_THRESHOLD,
+                    Settings.Global.RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD);
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
                  Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
@@ -664,6 +668,7 @@
                  Settings.Secure.SMS_DEFAULT_APPLICATION,
                  Settings.Secure.SPELL_CHECKER_ENABLED,  // Intentionally removed in Q
                  Settings.Secure.TRUST_AGENTS_INITIALIZED,
+                 Settings.Secure.TV_APP_USES_NON_SYSTEM_INPUTS,
                  Settings.Secure.TV_INPUT_CUSTOM_LABELS,
                  Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
                  Settings.Secure.TV_USER_SETUP_COMPLETE,
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index cb6f0e6..a5f5f67 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -34,9 +34,10 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
 
 import java.util.HashMap;
 import java.util.List;
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index b0d29bd..08f9de6 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -22,8 +22,9 @@
 
 import android.platform.test.annotations.Presubmit;
 import android.provider.SettingsValidators.Validator;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/provider/SmsProviderTest.java b/core/tests/coretests/src/android/provider/SmsProviderTest.java
index af4d1a6..67ac8ea 100644
--- a/core/tests/coretests/src/android/provider/SmsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SmsProviderTest.java
@@ -22,8 +22,9 @@
 import android.net.Uri;
 import android.provider.Telephony.Sms;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.Suppress;
 
 import java.util.GregorianCalendar;
 
diff --git a/core/tests/coretests/src/android/provider/TestFontsProvider.java b/core/tests/coretests/src/android/provider/TestFontsProvider.java
index 46906df..c3457fa 100644
--- a/core/tests/coretests/src/android/provider/TestFontsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestFontsProvider.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.provider;
 
 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
@@ -23,7 +24,6 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.MatrixCursor;
-import android.graphics.Typeface;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainProtectionParamsTest.java b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainProtectionParamsTest.java
index 0c9c4c1..ce0bf30 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainProtectionParamsTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainProtectionParamsTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java
index 61ab152..2a962c2 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.common.collect.Lists;
 
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/KeyDerivationParamsTest.java b/core/tests/coretests/src/android/security/keystore/recovery/KeyDerivationParamsTest.java
index b6af9bb..2b37b52 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/KeyDerivationParamsTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/KeyDerivationParamsTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/RecoveryCertPathTest.java b/core/tests/coretests/src/android/security/keystore/recovery/RecoveryCertPathTest.java
index dd8cd8d..3b8f715 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/RecoveryCertPathTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/RecoveryCertPathTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java b/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
index a5a3ca9..2b15d73 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/TrustedRootCertificatesTest.java
@@ -20,8 +20,8 @@
 
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java b/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java
index 15afbdd..8522e62 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/security/keystore/recovery/X509CertificateParsingUtilsTest.java b/core/tests/coretests/src/android/security/keystore/recovery/X509CertificateParsingUtilsTest.java
index 7f0eb43..17486d5 100644
--- a/core/tests/coretests/src/android/security/keystore/recovery/X509CertificateParsingUtilsTest.java
+++ b/core/tests/coretests/src/android/security/keystore/recovery/X509CertificateParsingUtilsTest.java
@@ -21,8 +21,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
index e69d1e7..d00d052 100644
--- a/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
+++ b/core/tests/coretests/src/android/service/euicc/EuiccProfileInfoTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.service.euicc;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -23,10 +24,11 @@
 
 import android.os.Parcel;
 import android.service.carrier.CarrierIdentifier;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.telephony.UiccAccessRule;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
index 8a3ba8c..4aa1000 100644
--- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
+++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.service.notification;
 
 import static junit.framework.Assert.assertEquals;
@@ -28,9 +29,10 @@
 import android.content.pm.PackageManager;
 import android.metrics.LogMaker;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/core/tests/coretests/src/android/service/settings/suggestions/MockSuggestionService.java b/core/tests/coretests/src/android/service/settings/suggestions/MockSuggestionService.java
index ab541a1..9c8e868 100644
--- a/core/tests/coretests/src/android/service/settings/suggestions/MockSuggestionService.java
+++ b/core/tests/coretests/src/android/service/settings/suggestions/MockSuggestionService.java
@@ -16,16 +16,12 @@
 
 package android.service.settings.suggestions;
 
-import android.support.annotation.VisibleForTesting;
-
 import java.util.ArrayList;
 import java.util.List;
 
 public class MockSuggestionService extends SuggestionService {
 
-    @VisibleForTesting
     static boolean sOnSuggestionLaunchedCalled;
-    @VisibleForTesting
     static boolean sOnSuggestionDismissedCalled;
 
     public static void reset() {
diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java
index dca8c09..64edda5 100644
--- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java
+++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionServiceTest.java
@@ -21,10 +21,11 @@
 import android.content.Intent;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.ServiceTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ServiceTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
index b0ec55d..8c47fcb 100644
--- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
+++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
@@ -24,9 +24,10 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/text/AndroidCharacterTest.java b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
index 0c7e730..1c5986a 100644
--- a/core/tests/coretests/src/android/text/AndroidCharacterTest.java
+++ b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
@@ -19,7 +19,8 @@
 import static org.junit.Assert.assertArrayEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
diff --git a/core/tests/coretests/src/android/text/BidiFormatterTest.java b/core/tests/coretests/src/android/text/BidiFormatterTest.java
index 1b936c7..312fb68 100644
--- a/core/tests/coretests/src/android/text/BidiFormatterTest.java
+++ b/core/tests/coretests/src/android/text/BidiFormatterTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
index c69f4f5..cca1ad3 100644
--- a/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
+++ b/core/tests/coretests/src/android/text/DynamicLayoutBlocksTest.java
@@ -22,8 +22,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java
index ea954f6..699243b 100644
--- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java
+++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java
@@ -27,11 +27,12 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.style.ReplacementSpan;
 import android.util.ArraySet;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/EmojiTest.java b/core/tests/coretests/src/android/text/EmojiTest.java
index 313f1b6..1948994 100644
--- a/core/tests/coretests/src/android/text/EmojiTest.java
+++ b/core/tests/coretests/src/android/text/EmojiTest.java
@@ -21,8 +21,9 @@
 
 import android.icu.lang.UCharacterDirection;
 import android.icu.text.Bidi;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/FontFallbackSetup.java b/core/tests/coretests/src/android/text/FontFallbackSetup.java
index 5592aac..cc51ec3 100644
--- a/core/tests/coretests/src/android/text/FontFallbackSetup.java
+++ b/core/tests/coretests/src/android/text/FontFallbackSetup.java
@@ -24,9 +24,10 @@
 import android.graphics.fonts.FontCustomizationParser;
 import android.graphics.fonts.FontFamily;
 import android.graphics.fonts.SystemFonts;
-import android.support.test.InstrumentationRegistry;
 import android.util.ArrayMap;
 
+import androidx.test.InstrumentationRegistry;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
diff --git a/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java
index 1208d7c..96e7fb9 100644
--- a/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java
+++ b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java
@@ -22,12 +22,13 @@
 import android.graphics.Path;
 import android.graphics.Typeface;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.method.MetaKeyKeyListener;
 import android.view.KeyEvent;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/LayoutTest.java b/core/tests/coretests/src/android/text/LayoutTest.java
index 97937a4..990161a 100644
--- a/core/tests/coretests/src/android/text/LayoutTest.java
+++ b/core/tests/coretests/src/android/text/LayoutTest.java
@@ -31,11 +31,12 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Layout.Alignment;
 import android.text.style.StrikethroughSpan;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index a0dca2c..57bb434 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -23,9 +23,10 @@
 
 import android.content.Context;
 import android.graphics.Typeface;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/PackedIntVectorTest.java b/core/tests/coretests/src/android/text/PackedIntVectorTest.java
index d9dc6fc..ba15b92 100644
--- a/core/tests/coretests/src/android/text/PackedIntVectorTest.java
+++ b/core/tests/coretests/src/android/text/PackedIntVectorTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
index d0f2d46..91b8c6a 100644
--- a/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
+++ b/core/tests/coretests/src/android/text/SpannableStringBuilderTest.java
@@ -16,18 +16,18 @@
 
 package android.text;
 
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.style.BulletSpan;
 import android.text.style.QuoteSpan;
 import android.text.style.SubscriptSpan;
 import android.text.style.UnderlineSpan;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java b/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java
index 6c05601..9149f7b 100644
--- a/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java
+++ b/core/tests/coretests/src/android/text/SpannableStringNoCopyTest.java
@@ -21,11 +21,12 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.annotation.NonNull;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.style.QuoteSpan;
 import android.text.style.UnderlineSpan;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/SpannableTest.java b/core/tests/coretests/src/android/text/SpannableTest.java
index f368428..d248a1f 100644
--- a/core/tests/coretests/src/android/text/SpannableTest.java
+++ b/core/tests/coretests/src/android/text/SpannableTest.java
@@ -19,10 +19,11 @@
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.MoreAsserts;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java b/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java
index 380e315..ca43733 100644
--- a/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java
+++ b/core/tests/coretests/src/android/text/SpannedStringNoCopyTest.java
@@ -21,11 +21,12 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.annotation.NonNull;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.style.QuoteSpan;
 import android.text.style.UnderlineSpan;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/SpannedTest.java b/core/tests/coretests/src/android/text/SpannedTest.java
index 5737571..3ab0755 100644
--- a/core/tests/coretests/src/android/text/SpannedTest.java
+++ b/core/tests/coretests/src/android/text/SpannedTest.java
@@ -21,13 +21,14 @@
 import android.graphics.Typeface;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.style.CharacterStyle;
 import android.text.style.StyleSpan;
 import android.text.style.TextAppearanceSpan;
 import android.text.style.TypefaceSpan;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
index bf0d427..32370b3e 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutBidiTest.java
@@ -19,10 +19,11 @@
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
index 5cf5426..4221ac2 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutDirectionsTest.java
@@ -19,11 +19,12 @@
 import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Layout.Directions;
 import android.text.StaticLayoutTest.LayoutBuilder;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 2521712..b1c896e 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -25,13 +25,14 @@
 import android.graphics.Paint.FontMetricsInt;
 import android.os.LocaleList;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Layout.Alignment;
 import android.text.method.EditorState;
 import android.text.style.LocaleSpan;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
index f6888e3..0d42326 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTextMeasuringTest.java
@@ -19,10 +19,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Layout.Alignment;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/TextLayoutTest.java b/core/tests/coretests/src/android/text/TextLayoutTest.java
index 24020ce..15fbc9e 100644
--- a/core/tests/coretests/src/android/text/TextLayoutTest.java
+++ b/core/tests/coretests/src/android/text/TextLayoutTest.java
@@ -17,8 +17,9 @@
 package android.text;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/text/TextLineTest.java b/core/tests/coretests/src/android/text/TextLineTest.java
index 2fe882c..90ce305 100644
--- a/core/tests/coretests/src/android/text/TextLineTest.java
+++ b/core/tests/coretests/src/android/text/TextLineTest.java
@@ -25,14 +25,15 @@
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Layout.TabStops;
 import android.text.style.ReplacementSpan;
 import android.text.style.TabStopSpan;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 72290bf..be6ef19 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -26,15 +26,16 @@
 
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.LargeTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.MoreAsserts;
 import android.text.style.StyleSpan;
 import android.text.util.Rfc822Token;
 import android.text.util.Rfc822Tokenizer;
 import android.view.View;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.google.android.collect.Lists;
 
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/text/VariationParserTest.java b/core/tests/coretests/src/android/text/VariationParserTest.java
index fbd2412..0afe811 100644
--- a/core/tests/coretests/src/android/text/VariationParserTest.java
+++ b/core/tests/coretests/src/android/text/VariationParserTest.java
@@ -21,8 +21,9 @@
 
 import android.graphics.fonts.FontVariationAxis;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java
index 9000ed0..5a0a84d 100644
--- a/core/tests/coretests/src/android/text/format/DateFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index 872b71a..381c051 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -22,8 +22,9 @@
 import android.content.res.Resources;
 import android.os.LocaleList;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index 82e4bff..068d047 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -25,11 +25,12 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.format.Formatter.BytesResult;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/text/format/TimeTest.java b/core/tests/coretests/src/android/text/format/TimeTest.java
index d563f2e..ac00411 100644
--- a/core/tests/coretests/src/android/text/format/TimeTest.java
+++ b/core/tests/coretests/src/android/text/format/TimeTest.java
@@ -21,12 +21,13 @@
 import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
 import android.util.TimeFormatException;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index df4609f..ddae652 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -17,15 +17,16 @@
 package android.text.method;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
 import android.widget.EditText;
 import android.widget.TextView.BufferType;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/method/EditorState.java b/core/tests/coretests/src/android/text/method/EditorState.java
index 12bb8c8..4eff7a4 100644
--- a/core/tests/coretests/src/android/text/method/EditorState.java
+++ b/core/tests/coretests/src/android/text/method/EditorState.java
@@ -21,8 +21,6 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import android.graphics.Canvas;
-import android.graphics.Paint;
 import android.text.Editable;
 import android.text.Spannable;
 import android.text.SpannableString;
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 45a5010..45b63e0 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -17,15 +17,16 @@
 package android.text.method;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.InputType;
 import android.util.KeyUtils;
 import android.view.KeyEvent;
 import android.widget.EditText;
 import android.widget.TextView.BufferType;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/method/WordIteratorTest.java b/core/tests/coretests/src/android/text/method/WordIteratorTest.java
index 6845863..cc345f5 100644
--- a/core/tests/coretests/src/android/text/method/WordIteratorTest.java
+++ b/core/tests/coretests/src/android/text/method/WordIteratorTest.java
@@ -22,8 +22,9 @@
 import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java
index 3d7e5ba..a0d2f85 100644
--- a/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java
+++ b/core/tests/coretests/src/android/text/style/UnderlineSpanTest.java
@@ -16,17 +16,17 @@
 
 package android.text.style;
 
-
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.StaticLayout;
 import android.text.TextPaint;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/text/util/LinkifyTest.java b/core/tests/coretests/src/android/text/util/LinkifyTest.java
index be3a0be..107ecd7 100644
--- a/core/tests/coretests/src/android/text/util/LinkifyTest.java
+++ b/core/tests/coretests/src/android/text/util/LinkifyTest.java
@@ -23,9 +23,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.LocaleList;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.method.LinkMovementMethod;
@@ -33,6 +30,10 @@
 import android.util.Patterns;
 import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/transition/AutoTransitionTest.java b/core/tests/coretests/src/android/transition/AutoTransitionTest.java
index 834fb7a..deae967 100644
--- a/core/tests/coretests/src/android/transition/AutoTransitionTest.java
+++ b/core/tests/coretests/src/android/transition/AutoTransitionTest.java
@@ -16,16 +16,16 @@
 
 package android.transition;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 @RunWith(AndroidJUnit4.class)
 public class AutoTransitionTest {
     @Test
diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
index 22365ba..2077d94 100644
--- a/core/tests/coretests/src/android/transition/FadeTransitionTest.java
+++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
@@ -22,13 +22,14 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.transition.Transition.TransitionListener;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.util.concurrent.CountDownLatch;
diff --git a/core/tests/coretests/src/android/transition/SlideTransitionTest.java b/core/tests/coretests/src/android/transition/SlideTransitionTest.java
index 8b9ec74..046e49df 100644
--- a/core/tests/coretests/src/android/transition/SlideTransitionTest.java
+++ b/core/tests/coretests/src/android/transition/SlideTransitionTest.java
@@ -19,18 +19,18 @@
 import android.animation.AnimatorSetActivity;
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-
 public class SlideTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
 
     Activity mActivity;
diff --git a/core/tests/coretests/src/android/transition/TransitionTest.java b/core/tests/coretests/src/android/transition/TransitionTest.java
index 7e629f9..f59c406 100644
--- a/core/tests/coretests/src/android/transition/TransitionTest.java
+++ b/core/tests/coretests/src/android/transition/TransitionTest.java
@@ -19,7 +19,6 @@
 import android.animation.AnimatorSetActivity;
 import android.app.Activity;
 import android.graphics.Rect;
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
 import android.transition.Transition.EpicenterCallback;
 import android.util.ArrayMap;
@@ -27,6 +26,8 @@
 import android.view.animation.AccelerateInterpolator;
 import android.widget.TextView;
 
+import androidx.test.filters.LargeTest;
+
 import com.android.frameworks.coretests.R;
 
 import java.lang.reflect.Field;
diff --git a/core/tests/coretests/src/android/util/ArrayMapTest.java b/core/tests/coretests/src/android/util/ArrayMapTest.java
index f0cc7f7..b212cf6 100644
--- a/core/tests/coretests/src/android/util/ArrayMapTest.java
+++ b/core/tests/coretests/src/android/util/ArrayMapTest.java
@@ -14,10 +14,10 @@
 
 package android.util;
 
-import android.support.test.filters.LargeTest;
-import android.util.ArrayMap;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
+
 import org.junit.Test;
 
 import java.util.ConcurrentModificationException;
diff --git a/core/tests/coretests/src/android/util/Base64Test.java b/core/tests/coretests/src/android/util/Base64Test.java
index af608c3..15c51af 100644
--- a/core/tests/coretests/src/android/util/Base64Test.java
+++ b/core/tests/coretests/src/android/util/Base64Test.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import android.support.test.filters.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/util/DataUnitTest.java b/core/tests/coretests/src/android/util/DataUnitTest.java
index 4eae8b4..ec296b7 100644
--- a/core/tests/coretests/src/android/util/DataUnitTest.java
+++ b/core/tests/coretests/src/android/util/DataUnitTest.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java b/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
index 4c5ad76..572e9b0 100644
--- a/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
+++ b/core/tests/coretests/src/android/util/DayOfMonthCursorTest.java
@@ -16,10 +16,11 @@
 
 package android.util;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 import java.util.Calendar;
-import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * Unit tests for {@link DayOfMonthCursor}.
diff --git a/core/tests/coretests/src/android/util/InternalSelectionView.java b/core/tests/coretests/src/android/util/InternalSelectionView.java
index a0fb0f1..4a1baef 100644
--- a/core/tests/coretests/src/android/util/InternalSelectionView.java
+++ b/core/tests/coretests/src/android/util/InternalSelectionView.java
@@ -16,19 +16,16 @@
 
 package android.util;
 
-import com.android.frameworks.coretests.R;
-
-import android.view.View;
-import android.view.KeyEvent;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Paint;
 import android.graphics.Canvas;
-import android.graphics.Rect;
 import android.graphics.Color;
-import android.util.AttributeSet;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.view.KeyEvent;
+import android.view.View;
 
-
+import com.android.frameworks.coretests.R;
 
 /**
  * A view that has a known number of selectable rows, and maintains a notion of which
diff --git a/core/tests/coretests/src/android/util/KeyUtils.java b/core/tests/coretests/src/android/util/KeyUtils.java
index 593f727..612643e 100644
--- a/core/tests/coretests/src/android/util/KeyUtils.java
+++ b/core/tests/coretests/src/android/util/KeyUtils.java
@@ -17,16 +17,10 @@
 package android.util;
 
 import android.app.Instrumentation;
-import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.InstrumentationTestCase;
-import android.view.Gravity;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 
 /**
  * Reusable methods for generating key events.
diff --git a/core/tests/coretests/src/android/util/KeyValueListParserTest.java b/core/tests/coretests/src/android/util/KeyValueListParserTest.java
index 038f0b7..f65c4c7 100644
--- a/core/tests/coretests/src/android/util/KeyValueListParserTest.java
+++ b/core/tests/coretests/src/android/util/KeyValueListParserTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/util/ListUtil.java b/core/tests/coretests/src/android/util/ListUtil.java
index 2a7cb96..3748cf8 100644
--- a/core/tests/coretests/src/android/util/ListUtil.java
+++ b/core/tests/coretests/src/android/util/ListUtil.java
@@ -20,13 +20,11 @@
 import android.view.KeyEvent;
 import android.widget.ListView;
 
-
 /**
  * Various useful stuff for instrumentation testing listview.
  */
 public class ListUtil {
 
-
     private final ListView mListView;
     private final Instrumentation mInstrumentation;
 
diff --git a/core/tests/coretests/src/android/util/LocalLogTest.java b/core/tests/coretests/src/android/util/LocalLogTest.java
index 5144c85e..6cdcb5e 100644
--- a/core/tests/coretests/src/android/util/LocalLogTest.java
+++ b/core/tests/coretests/src/android/util/LocalLogTest.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import android.support.test.filters.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/util/LogNullabilityTest.java b/core/tests/coretests/src/android/util/LogNullabilityTest.java
index 3f4776d..370885d 100644
--- a/core/tests/coretests/src/android/util/LogNullabilityTest.java
+++ b/core/tests/coretests/src/android/util/LogNullabilityTest.java
@@ -19,8 +19,8 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/util/LogTest.java b/core/tests/coretests/src/android/util/LogTest.java
index 30c81b0..d783c12 100644
--- a/core/tests/coretests/src/android/util/LogTest.java
+++ b/core/tests/coretests/src/android/util/LogTest.java
@@ -16,13 +16,12 @@
 
 package android.util;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
 import android.os.SystemProperties;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.Suppress;
-import android.util.Log;
+
+import androidx.test.filters.Suppress;
+
+import junit.framework.TestCase;
 
 //This is an empty TestCase.
 @Suppress
diff --git a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
index 3f03db9..a1d48e6 100644
--- a/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
+++ b/core/tests/coretests/src/android/util/LongSparseLongArrayTest.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import android.support.test.filters.LargeTest;
+import androidx.test.filters.LargeTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/util/LruCacheTest.java b/core/tests/coretests/src/android/util/LruCacheTest.java
index 5a97158..1928bfd 100644
--- a/core/tests/coretests/src/android/util/LruCacheTest.java
+++ b/core/tests/coretests/src/android/util/LruCacheTest.java
@@ -16,12 +16,13 @@
 
 package android.util;
 
+import junit.framework.TestCase;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import junit.framework.TestCase;
 
 public final class LruCacheTest extends TestCase {
     private int expectedCreateCount;
diff --git a/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java b/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
index 55da665..30d5f77 100644
--- a/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
+++ b/core/tests/coretests/src/android/util/MonthDisplayHelperTest.java
@@ -16,12 +16,12 @@
 
 package android.util;
 
-import android.test.suitebuilder.annotation.SmallTest;
-
-import java.util.Calendar;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
+import java.util.Calendar;
+
 /**
  * Unit tests for {@link MonthDisplayHelper}.
  */
diff --git a/core/tests/coretests/src/android/util/OrientationUtil.java b/core/tests/coretests/src/android/util/OrientationUtil.java
index ecdca5d..0361194 100644
--- a/core/tests/coretests/src/android/util/OrientationUtil.java
+++ b/core/tests/coretests/src/android/util/OrientationUtil.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.pm.ActivityInfo;
-
 import android.test.ActivityInstrumentationTestCase2;
 
 import com.android.internal.util.Preconditions;
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index 360b875..6cea2f3 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -13,15 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.util;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
+
+import junit.framework.TestCase;
 
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import junit.framework.TestCase;
-
 public class PatternsTest extends TestCase {
 
     // Tests for Patterns.TOP_LEVEL_DOMAIN
diff --git a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
index 39d492d..caa1208 100644
--- a/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
+++ b/core/tests/coretests/src/android/util/RecurrenceRuleTest.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/util/SparseLongArrayTest.java b/core/tests/coretests/src/android/util/SparseLongArrayTest.java
index 5a5e893..df2d752 100644
--- a/core/tests/coretests/src/android/util/SparseLongArrayTest.java
+++ b/core/tests/coretests/src/android/util/SparseLongArrayTest.java
@@ -19,9 +19,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import android.support.annotation.NonNull;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import android.annotation.NonNull;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/util/StateSetTest.java b/core/tests/coretests/src/android/util/StateSetTest.java
index e481ce0..b5d6270 100644
--- a/core/tests/coretests/src/android/util/StateSetTest.java
+++ b/core/tests/coretests/src/android/util/StateSetTest.java
@@ -16,8 +16,9 @@
 
 package android.util;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * Tests for {@link StateSet}
diff --git a/core/tests/coretests/src/android/util/TimestampedValueTest.java b/core/tests/coretests/src/android/util/TimestampedValueTest.java
index 03b4abd..6e3ab79 100644
--- a/core/tests/coretests/src/android/util/TimestampedValueTest.java
+++ b/core/tests/coretests/src/android/util/TimestampedValueTest.java
@@ -21,7 +21,8 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/util/TimingsTraceLogTest.java b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
index 7bb4ab8..77d0552 100644
--- a/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
+++ b/core/tests/coretests/src/android/util/TimingsTraceLogTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Trace;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,7 +29,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-
 /**
  * Tests for {@link TimingsTraceLog}.
  * <p>Usage: bit FrameworksCoreTests:android.util.TimingsTraceLogTest
diff --git a/core/tests/coretests/src/android/util/TouchModeFlexibleAsserts.java b/core/tests/coretests/src/android/util/TouchModeFlexibleAsserts.java
index ca12a15..fc08235 100644
--- a/core/tests/coretests/src/android/util/TouchModeFlexibleAsserts.java
+++ b/core/tests/coretests/src/android/util/TouchModeFlexibleAsserts.java
@@ -16,12 +16,12 @@
 
 package android.util;
 
-import junit.framework.Assert;
-
 import android.test.InstrumentationTestCase;
 import android.test.TouchUtils;
 import android.view.View;
 
+import junit.framework.Assert;
+
 /**
  * When entering touch mode via touch, the tests can be flaky.  These asserts
  * are more flexible (allowing up to MAX_ATTEMPTS touches to enter touch mode via touch or
diff --git a/core/tests/coretests/src/android/view/BigCache.java b/core/tests/coretests/src/android/view/BigCache.java
index 2182176..6a1bcaa 100644
--- a/core/tests/coretests/src/android/view/BigCache.java
+++ b/core/tests/coretests/src/android/view/BigCache.java
@@ -16,16 +16,12 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.app.Activity;
+import android.os.Bundle;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
-import android.view.ViewGroup;
-import android.view.View;
-import android.view.Display;
-import android.view.ViewConfiguration;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * This activity contains two Views, one as big as the screen, one much larger. The large one
diff --git a/core/tests/coretests/src/android/view/BigCacheTest.java b/core/tests/coretests/src/android/view/BigCacheTest.java
index 8c2c865..ed4b996 100644
--- a/core/tests/coretests/src/android/view/BigCacheTest.java
+++ b/core/tests/coretests/src/android/view/BigCacheTest.java
@@ -16,14 +16,12 @@
 
 package android.view;
 
-import android.view.BigCache;
-import com.android.frameworks.coretests.R;
-
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
-import android.view.ViewConfiguration;
 import android.graphics.Bitmap;
+import android.test.ActivityInstrumentationTestCase;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Builds the drawing cache of two Views, one smaller than the maximum cache size,
diff --git a/core/tests/coretests/src/android/view/BitmapDrawable.java b/core/tests/coretests/src/android/view/BitmapDrawable.java
index f7bad84..42c176f 100644
--- a/core/tests/coretests/src/android/view/BitmapDrawable.java
+++ b/core/tests/coretests/src/android/view/BitmapDrawable.java
@@ -16,19 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AbsoluteLayout;
-import android.widget.Button;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
+
+import com.android.frameworks.coretests.R;
 
 public class BitmapDrawable extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/view/CreateViewTest.java b/core/tests/coretests/src/android/view/CreateViewTest.java
index 16656f6..520f83f 100644
--- a/core/tests/coretests/src/android/view/CreateViewTest.java
+++ b/core/tests/coretests/src/android/view/CreateViewTest.java
@@ -16,16 +16,17 @@
 
 package android.view;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
 import android.content.Context;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.test.filters.SmallTest;
+
 public class CreateViewTest extends AndroidTestCase implements PerformanceTestCase {
 
     public boolean isPerformanceOnly() {
diff --git a/core/tests/coretests/src/android/view/Disabled.java b/core/tests/coretests/src/android/view/Disabled.java
index d3c7470..ce90039 100644
--- a/core/tests/coretests/src/android/view/Disabled.java
+++ b/core/tests/coretests/src/android/view/Disabled.java
@@ -16,13 +16,12 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
-import android.widget.Button;
-import android.view.View;
-import android.view.View.OnClickListener;
 import android.app.Activity;
+import android.os.Bundle;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise View's disabled state.
diff --git a/core/tests/coretests/src/android/view/DisabledLongpressTest.java b/core/tests/coretests/src/android/view/DisabledLongpressTest.java
index faa0865..a9fec01 100644
--- a/core/tests/coretests/src/android/view/DisabledLongpressTest.java
+++ b/core/tests/coretests/src/android/view/DisabledLongpressTest.java
@@ -18,11 +18,12 @@
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.KeyUtils;
 import android.view.View.OnLongClickListener;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/DisabledTest.java b/core/tests/coretests/src/android/view/DisabledTest.java
index 291a11c..8922e5f 100644
--- a/core/tests/coretests/src/android/view/DisabledTest.java
+++ b/core/tests/coretests/src/android/view/DisabledTest.java
@@ -18,12 +18,11 @@
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.KeyEvent;
-import android.view.View;
 import android.widget.Button;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index 8e4f2cd..dd50af877 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -33,17 +33,17 @@
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.DisplayCutout.ParcelableWrapper;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.Collections;
 
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 @Presubmit
diff --git a/core/tests/coretests/src/android/view/DrawableBgMinSize.java b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
index 58bfb8a..ba9ba00 100644
--- a/core/tests/coretests/src/android/view/DrawableBgMinSize.java
+++ b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
@@ -16,12 +16,9 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.AbsoluteLayout;
 import android.widget.Button;
@@ -30,6 +27,8 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Views should obey their background {@link Drawable}'s minimum size
  * requirements ({@link Drawable#getMinimumHeight()} and
diff --git a/core/tests/coretests/src/android/view/DrawableBgMinSizeTest.java b/core/tests/coretests/src/android/view/DrawableBgMinSizeTest.java
index e705c87..1735e8c 100644
--- a/core/tests/coretests/src/android/view/DrawableBgMinSizeTest.java
+++ b/core/tests/coretests/src/android/view/DrawableBgMinSizeTest.java
@@ -16,14 +16,9 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-import android.view.DrawableBgMinSize;
-import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.MediumTest;
-
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase;
-import android.view.View;
+import android.test.TouchUtils;
 import android.widget.AbsoluteLayout;
 import android.widget.Button;
 import android.widget.FrameLayout;
@@ -31,6 +26,10 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link DrawableBgMinSize} exercises Views to obey their background drawable's
  * minimum sizes.
diff --git a/core/tests/coretests/src/android/view/FocusFinderTest.java b/core/tests/coretests/src/android/view/FocusFinderTest.java
index 2732a04..b35c64a 100644
--- a/core/tests/coretests/src/android/view/FocusFinderTest.java
+++ b/core/tests/coretests/src/android/view/FocusFinderTest.java
@@ -18,7 +18,8 @@
 
 import android.graphics.Rect;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 public class FocusFinderTest extends AndroidTestCase {
 
diff --git a/core/tests/coretests/src/android/view/GlobalFocusChange.java b/core/tests/coretests/src/android/view/GlobalFocusChange.java
index 041c0de..ee92b64 100644
--- a/core/tests/coretests/src/android/view/GlobalFocusChange.java
+++ b/core/tests/coretests/src/android/view/GlobalFocusChange.java
@@ -16,12 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.ViewTreeObserver;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class GlobalFocusChange extends Activity implements ViewTreeObserver.OnGlobalFocusChangeListener {
     public View mOldFocus;
diff --git a/core/tests/coretests/src/android/view/GlobalFocusChangeTest.java b/core/tests/coretests/src/android/view/GlobalFocusChangeTest.java
index dab7b90..960654a 100644
--- a/core/tests/coretests/src/android/view/GlobalFocusChangeTest.java
+++ b/core/tests/coretests/src/android/view/GlobalFocusChangeTest.java
@@ -17,13 +17,13 @@
 package android.view;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.FlakyTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.Suppress;
-import android.view.View;
-import android.view.KeyEvent;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 import com.android.frameworks.coretests.R;
 
 @Suppress // Flaky
@@ -50,7 +50,7 @@
         super.tearDown();
     }
 
-    @FlakyTest(tolerance = 4)
+    @FlakyTest
     @LargeTest
     public void testFocusChange() throws Exception {
         sendKeys(KeyEvent.KEYCODE_DPAD_RIGHT);
@@ -62,7 +62,7 @@
         assertSame(mRight, mActivity.mNewFocus);        
     }
 
-    @FlakyTest(tolerance = 4)
+    @FlakyTest
     @MediumTest
     public void testEnterTouchMode() throws Exception {
         assertTrue(mLeft.isFocused());
@@ -73,7 +73,7 @@
         assertSame(null, mActivity.mNewFocus);        
     }
 
-    @FlakyTest(tolerance = 4)
+    @FlakyTest
     @MediumTest
     public void testLeaveTouchMode() throws Exception {
         assertTrue(mLeft.isFocused());
diff --git a/core/tests/coretests/src/android/view/HandlerActionQueueTest.java b/core/tests/coretests/src/android/view/HandlerActionQueueTest.java
index fd8f23a..bedb75b 100644
--- a/core/tests/coretests/src/android/view/HandlerActionQueueTest.java
+++ b/core/tests/coretests/src/android/view/HandlerActionQueueTest.java
@@ -17,7 +17,8 @@
 package android.view;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 public class HandlerActionQueueTest extends AndroidTestCase {
 
diff --git a/core/tests/coretests/src/android/view/Include.java b/core/tests/coretests/src/android/view/Include.java
index e90c484..4b6aefb 100644
--- a/core/tests/coretests/src/android/view/Include.java
+++ b/core/tests/coretests/src/android/view/Include.java
@@ -16,10 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise <include /> tag in XML files.
diff --git a/core/tests/coretests/src/android/view/IncludeTest.java b/core/tests/coretests/src/android/view/IncludeTest.java
index cdcfa3c..e490559 100644
--- a/core/tests/coretests/src/android/view/IncludeTest.java
+++ b/core/tests/coretests/src/android/view/IncludeTest.java
@@ -16,13 +16,11 @@
 
 package android.view;
 
-import android.view.Include;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
-import android.view.ViewGroup;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 public class IncludeTest extends ActivityInstrumentationTestCase<Include> {
     public IncludeTest() {
diff --git a/core/tests/coretests/src/android/view/InflateTest.java b/core/tests/coretests/src/android/view/InflateTest.java
index cb4f8e2..939d6ea 100644
--- a/core/tests/coretests/src/android/view/InflateTest.java
+++ b/core/tests/coretests/src/android/view/InflateTest.java
@@ -20,13 +20,11 @@
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.test.PerformanceTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import com.android.frameworks.coretests.R;
 
-import java.util.Map;
+import androidx.test.filters.SmallTest;
+
+import com.android.frameworks.coretests.R;
 
 public class InflateTest extends AndroidTestCase implements PerformanceTestCase {
     private LayoutInflater mInflater;
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 81ca910..7f00ad9 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -18,7 +18,9 @@
 
 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.TYPE_TOP_BAR;
+
 import static junit.framework.Assert.assertEquals;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
@@ -27,12 +29,13 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 import android.view.SurfaceControl.Transaction;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index d3d274a..d447451 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -17,18 +17,20 @@
 package android.view;
 
 import static android.view.InsetsState.TYPE_TOP_BAR;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
+
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
 
 @Presubmit
 @FlakyTest(detail = "Promote once confirmed non-flaky")
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 6d0f984..82cd213 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -17,6 +17,7 @@
 package android.view;
 
 import static android.view.InsetsState.TYPE_TOP_BAR;
+
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.reset;
@@ -24,10 +25,11 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.SurfaceControl.Transaction;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index ed472d2..98ab3e7 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -17,13 +17,15 @@
 package android.view;
 
 import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+
 import static junit.framework.Assert.assertEquals;
 
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 95af525..9857b7a 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -24,20 +24,23 @@
 import static android.view.InsetsState.TYPE_SIDE_BAR_2;
 import static android.view.InsetsState.TYPE_SIDE_BAR_3;
 import static android.view.InsetsState.TYPE_TOP_BAR;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
+
 import static org.junit.Assert.assertNotEquals;
 
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseIntArray;
 import android.view.WindowInsets.Type;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index b9d95e5..88d3bdb 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -20,8 +20,8 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/ListContextMenu.java b/core/tests/coretests/src/android/view/ListContextMenu.java
index 1b4ece6..e333b96 100644
--- a/core/tests/coretests/src/android/view/ListContextMenu.java
+++ b/core/tests/coretests/src/android/view/ListContextMenu.java
@@ -16,24 +16,17 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.os.Bundle;
 import android.util.Log;
-import android.view.ContextMenu;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.SubMenu;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercises context menus in lists
  */
diff --git a/core/tests/coretests/src/android/view/Longpress.java b/core/tests/coretests/src/android/view/Longpress.java
index e8e6f13..86fa9e5 100644
--- a/core/tests/coretests/src/android/view/Longpress.java
+++ b/core/tests/coretests/src/android/view/Longpress.java
@@ -16,11 +16,11 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class Longpress extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/core/tests/coretests/src/android/view/LongpressTest.java b/core/tests/coretests/src/android/view/LongpressTest.java
index d3d7589..4dfecd0 100644
--- a/core/tests/coretests/src/android/view/LongpressTest.java
+++ b/core/tests/coretests/src/android/view/LongpressTest.java
@@ -18,11 +18,12 @@
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.KeyUtils;
 import android.view.View.OnLongClickListener;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/MenuTest.java b/core/tests/coretests/src/android/view/MenuTest.java
index 116b38a..794769cc 100644
--- a/core/tests/coretests/src/android/view/MenuTest.java
+++ b/core/tests/coretests/src/android/view/MenuTest.java
@@ -17,7 +17,8 @@
 package android.view;
 
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.coretests.R;
 import com.android.internal.view.menu.MenuBuilder;
diff --git a/core/tests/coretests/src/android/view/Merge.java b/core/tests/coretests/src/android/view/Merge.java
index bdacd81..8020e4b 100644
--- a/core/tests/coretests/src/android/view/Merge.java
+++ b/core/tests/coretests/src/android/view/Merge.java
@@ -16,13 +16,11 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.app.Activity;
+import android.os.Bundle;
 import android.widget.LinearLayout;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise <merge /> tag in XML files.
diff --git a/core/tests/coretests/src/android/view/MergeTest.java b/core/tests/coretests/src/android/view/MergeTest.java
index acfee7e..eccc9cb 100644
--- a/core/tests/coretests/src/android/view/MergeTest.java
+++ b/core/tests/coretests/src/android/view/MergeTest.java
@@ -16,11 +16,9 @@
 
 package android.view;
 
-import android.view.Merge;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.ViewGroup;
+
+import androidx.test.filters.MediumTest;
 
 public class MergeTest extends ActivityInstrumentationTestCase<Merge> {
     public MergeTest() {
diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java
index 023526f..cadf37e 100644
--- a/core/tests/coretests/src/android/view/MotionEventTest.java
+++ b/core/tests/coretests/src/android/view/MotionEventTest.java
@@ -22,11 +22,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/MutateDrawable.java b/core/tests/coretests/src/android/view/MutateDrawable.java
index 39b5789..1ec525d 100644
--- a/core/tests/coretests/src/android/view/MutateDrawable.java
+++ b/core/tests/coretests/src/android/view/MutateDrawable.java
@@ -18,8 +18,9 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.LinearLayout;
 import android.widget.Button;
+import android.widget.LinearLayout;
+
 import com.android.frameworks.coretests.R;
 
 public class MutateDrawable extends Activity {
diff --git a/core/tests/coretests/src/android/view/MutateDrawableTest.java b/core/tests/coretests/src/android/view/MutateDrawableTest.java
index 74e011d..d63ffb1 100644
--- a/core/tests/coretests/src/android/view/MutateDrawableTest.java
+++ b/core/tests/coretests/src/android/view/MutateDrawableTest.java
@@ -17,9 +17,8 @@
 package android.view;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
-import android.view.MutateDrawable;
+
+import androidx.test.filters.MediumTest;
 
 public class MutateDrawableTest extends ActivityInstrumentationTestCase2<MutateDrawable> {
     private View mFirstButton;
diff --git a/core/tests/coretests/src/android/view/PinchZoomAction.java b/core/tests/coretests/src/android/view/PinchZoomAction.java
index 97fe980..bec9b55 100644
--- a/core/tests/coretests/src/android/view/PinchZoomAction.java
+++ b/core/tests/coretests/src/android/view/PinchZoomAction.java
@@ -30,8 +30,6 @@
 import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.action.Swiper;
 import android.support.test.espresso.util.HumanReadables;
-import android.view.MotionEvent;
-import android.view.View;
 
 import org.hamcrest.Matcher;
 
diff --git a/core/tests/coretests/src/android/view/PopupWindowVisibility.java b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
index 85ce04f..e6430d3 100644
--- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java
+++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.AutoCompleteTextView;
diff --git a/core/tests/coretests/src/android/view/PreDrawListener.java b/core/tests/coretests/src/android/view/PreDrawListener.java
index 60bbee4..77bd36c 100644
--- a/core/tests/coretests/src/android/view/PreDrawListener.java
+++ b/core/tests/coretests/src/android/view/PreDrawListener.java
@@ -20,15 +20,12 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
 import com.android.frameworks.coretests.R;
 
-
 /**
  * Tests views with popupWindows becoming invisible
  */
diff --git a/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java
index b52d98c..786c22b 100644
--- a/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java
+++ b/core/tests/coretests/src/android/view/RenderNodeAnimatorTest.java
@@ -21,10 +21,11 @@
 
 import android.app.Activity;
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
 
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/RunQueue.java b/core/tests/coretests/src/android/view/RunQueue.java
index 85dd32e..7544433 100644
--- a/core/tests/coretests/src/android/view/RunQueue.java
+++ b/core/tests/coretests/src/android/view/RunQueue.java
@@ -19,8 +19,7 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.widget.TextView;
-import android.view.View;
-import android.view.ViewTreeObserver;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/RunQueueTest.java b/core/tests/coretests/src/android/view/RunQueueTest.java
index d69860b..f42f590 100644
--- a/core/tests/coretests/src/android/view/RunQueueTest.java
+++ b/core/tests/coretests/src/android/view/RunQueueTest.java
@@ -17,7 +17,8 @@
 package android.view;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.MediumTest;
 
 public class RunQueueTest extends ActivityInstrumentationTestCase<RunQueue> {
     public RunQueueTest() {
diff --git a/core/tests/coretests/src/android/view/ScaleGesture.java b/core/tests/coretests/src/android/view/ScaleGesture.java
index a954a4a..235b224 100644
--- a/core/tests/coretests/src/android/view/ScaleGesture.java
+++ b/core/tests/coretests/src/android/view/ScaleGesture.java
@@ -16,16 +16,11 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
 import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
-import android.widget.TextView;
+
+import com.android.frameworks.coretests.R;
 
 public class ScaleGesture extends Activity {
     private ScaleGestureDetector mScaleGestureDetector;
diff --git a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java
index fba8eae..19901351 100644
--- a/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java
+++ b/core/tests/coretests/src/android/view/ScaleGestureDetectorTest.java
@@ -16,26 +16,22 @@
 
 package android.view;
 
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
 import android.content.Context;
-import android.support.test.filters.LargeTest;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.DisplayMetrics;
-import android.view.PinchZoomAction;
-import android.view.ScaleGesture;
-import android.view.WindowManager;
 import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.Espresso.onView;
 
 @LargeTest
 public class ScaleGestureDetectorTest extends ActivityInstrumentationTestCase2<ScaleGesture> {
diff --git a/core/tests/coretests/src/android/view/SetTagsTest.java b/core/tests/coretests/src/android/view/SetTagsTest.java
index 373dce6..1699713 100644
--- a/core/tests/coretests/src/android/view/SetTagsTest.java
+++ b/core/tests/coretests/src/android/view/SetTagsTest.java
@@ -16,12 +16,13 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-import android.test.suitebuilder.annotation.MediumTest;
-
 import android.test.ActivityInstrumentationTestCase2;
 import android.widget.Button;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercises {@link android.view.View}'s tags property.
  */
diff --git a/core/tests/coretests/src/android/view/StubbedView.java b/core/tests/coretests/src/android/view/StubbedView.java
index 612095c..c96b9b7 100644
--- a/core/tests/coretests/src/android/view/StubbedView.java
+++ b/core/tests/coretests/src/android/view/StubbedView.java
@@ -16,11 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.app.Activity;
-import android.view.View;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise <ViewStub /> tag in XML files.
diff --git a/core/tests/coretests/src/android/view/VelocityTest.java b/core/tests/coretests/src/android/view/VelocityTest.java
index 7f32208..c116f4d 100644
--- a/core/tests/coretests/src/android/view/VelocityTest.java
+++ b/core/tests/coretests/src/android/view/VelocityTest.java
@@ -16,16 +16,17 @@
 
 package android.view;
 
-import android.test.suitebuilder.annotation.Suppress;
-import junit.framework.Assert;
-
 import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
+import junit.framework.Assert;
+
 /**
  * Exercises {@link android.view.VelocityTracker} to compute correct velocity.<br>
  * To launch this test, use :<br>
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
index aa8f8d8..1a8dd99 100644
--- a/core/tests/coretests/src/android/view/ViewAttachTest.java
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -16,16 +16,13 @@
 
 package android.view;
 
-import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.graphics.PixelFormat;
 import android.os.SystemClock;
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/view/ViewAttachTestActivity.java b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
index 59e25ae..bcbc813 100644
--- a/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
+++ b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
@@ -16,11 +16,11 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class ViewAttachTestActivity extends Activity {
     public static final String TAG = "OnAttachedTest";
     @Override
diff --git a/core/tests/coretests/src/android/view/ViewAttachView.java b/core/tests/coretests/src/android/view/ViewAttachView.java
index 5af2d8f..2f3ff8f 100644
--- a/core/tests/coretests/src/android/view/ViewAttachView.java
+++ b/core/tests/coretests/src/android/view/ViewAttachView.java
@@ -22,7 +22,6 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 
 /**
  * A View that will throw a RuntimeException if onAttachedToWindow and
diff --git a/core/tests/coretests/src/android/view/ViewCaptureTest.java b/core/tests/coretests/src/android/view/ViewCaptureTest.java
index 4405934..218047c 100644
--- a/core/tests/coretests/src/android/view/ViewCaptureTest.java
+++ b/core/tests/coretests/src/android/view/ViewCaptureTest.java
@@ -21,14 +21,15 @@
 import android.app.Activity;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.support.test.filters.SmallTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseIntArray;
 import android.view.ViewDebug.CanvasProvider;
 import android.view.ViewDebug.HardwareCanvasProvider;
 import android.view.ViewDebug.SoftwareCanvasProvider;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Assert;
diff --git a/core/tests/coretests/src/android/view/ViewCaptureTestActivity.java b/core/tests/coretests/src/android/view/ViewCaptureTestActivity.java
index 20e3eb5..2f51c24 100644
--- a/core/tests/coretests/src/android/view/ViewCaptureTestActivity.java
+++ b/core/tests/coretests/src/android/view/ViewCaptureTestActivity.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.os.Bundle;
+
 import com.android.frameworks.coretests.R;
 
 public class ViewCaptureTestActivity extends Activity {
diff --git a/core/tests/coretests/src/android/view/ViewGroupAttributesTest.java b/core/tests/coretests/src/android/view/ViewGroupAttributesTest.java
index b4ef0e7..c24cd35 100644
--- a/core/tests/coretests/src/android/view/ViewGroupAttributesTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupAttributesTest.java
@@ -18,7 +18,8 @@
 
 import android.content.Context;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 public class ViewGroupAttributesTest extends AndroidTestCase {
 
diff --git a/core/tests/coretests/src/android/view/ViewGroupChildren.java b/core/tests/coretests/src/android/view/ViewGroupChildren.java
index f39720b..d5d9879 100644
--- a/core/tests/coretests/src/android/view/ViewGroupChildren.java
+++ b/core/tests/coretests/src/android/view/ViewGroupChildren.java
@@ -16,12 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
-import android.widget.Button;
-import android.view.View;
 import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise ViewGroup's ability to add and remove children.
diff --git a/core/tests/coretests/src/android/view/ViewGroupChildrenTest.java b/core/tests/coretests/src/android/view/ViewGroupChildrenTest.java
index d1665ef..07cb2a1 100644
--- a/core/tests/coretests/src/android/view/ViewGroupChildrenTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupChildrenTest.java
@@ -16,18 +16,16 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-import android.view.ViewGroupChildren;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
-import android.test.UiThreadTest;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercises {@link android.view.ViewGroup}'s ability to add/remove children.
  */
diff --git a/core/tests/coretests/src/android/view/ViewGroupTransientViewTest.java b/core/tests/coretests/src/android/view/ViewGroupTransientViewTest.java
index 93ad41f0..54524b2 100644
--- a/core/tests/coretests/src/android/view/ViewGroupTransientViewTest.java
+++ b/core/tests/coretests/src/android/view/ViewGroupTransientViewTest.java
@@ -22,12 +22,13 @@
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.widget.FrameLayout;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/ViewInvalidateTest.java b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
index 115504b..c25a2deb 100644
--- a/core/tests/coretests/src/android/view/ViewInvalidateTest.java
+++ b/core/tests/coretests/src/android/view/ViewInvalidateTest.java
@@ -21,24 +21,30 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.LargeTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+import android.view.ViewTreeObserver.OnDrawListener;
 import android.widget.FrameLayout;
 
-import com.android.compatibility.common.util.WidgetTestUtils;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Test of invalidates, drawing, and the flags that support them
  */
@@ -281,4 +287,42 @@
                 View.PFLAG_DRAWN);
         assertTrue(getViewRoot(mParent).mIsAnimating);
     }
+
+    /** Copied from cts/common/device-side/util. */
+    static class WidgetTestUtils {
+        public static void runOnMainAndDrawSync(@NonNull final ActivityTestRule activityTestRule,
+                @NonNull final View view, @Nullable final Runnable runner) throws Throwable {
+            final CountDownLatch latch = new CountDownLatch(1);
+
+            activityTestRule.runOnUiThread(() -> {
+                final OnDrawListener listener = new OnDrawListener() {
+                    @Override
+                    public void onDraw() {
+                        // posting so that the sync happens after the draw that's about to happen
+                        view.post(() -> {
+                            activityTestRule.getActivity().getWindow().getDecorView()
+                                    .getViewTreeObserver().removeOnDrawListener(this);
+                            latch.countDown();
+                        });
+                    }
+                };
+
+                activityTestRule.getActivity().getWindow().getDecorView()
+                        .getViewTreeObserver().addOnDrawListener(listener);
+
+                if (runner != null) {
+                    runner.run();
+                }
+                view.invalidate();
+            });
+
+            try {
+                Assert.assertTrue("Expected draw pass occurred within 5 seconds",
+                        latch.await(5, TimeUnit.SECONDS));
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
 }
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index ca6d6cfe..9a57847 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -23,9 +23,10 @@
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/ViewStubTest.java b/core/tests/coretests/src/android/view/ViewStubTest.java
index ebd52a6..504a4ec 100644
--- a/core/tests/coretests/src/android/view/ViewStubTest.java
+++ b/core/tests/coretests/src/android/view/ViewStubTest.java
@@ -16,14 +16,12 @@
 
 package android.view;
 
-import android.view.StubbedView;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.UiThreadTest;
-import android.view.View;
-import android.view.ViewStub;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 public class ViewStubTest extends ActivityInstrumentationTestCase<StubbedView> {
     public ViewStubTest() {
diff --git a/core/tests/coretests/src/android/view/ViewTransientStateTest.java b/core/tests/coretests/src/android/view/ViewTransientStateTest.java
index 36ea01d..3f73b07 100644
--- a/core/tests/coretests/src/android/view/ViewTransientStateTest.java
+++ b/core/tests/coretests/src/android/view/ViewTransientStateTest.java
@@ -18,13 +18,12 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
 
 import com.android.frameworks.coretests.R;
 
-import static org.junit.Assert.assertFalse;
-
 /**
  * Exercise set View's transient state
  */
diff --git a/core/tests/coretests/src/android/view/Visibility.java b/core/tests/coretests/src/android/view/Visibility.java
index 031568c..8e3de4e 100644
--- a/core/tests/coretests/src/android/view/Visibility.java
+++ b/core/tests/coretests/src/android/view/Visibility.java
@@ -16,12 +16,11 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
+import android.app.Activity;
 import android.os.Bundle;
 import android.widget.Button;
-import android.view.View;
-import android.app.Activity;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise View's ability to change their visibility: GONE, INVISIBLE and
diff --git a/core/tests/coretests/src/android/view/VisibilityCallback.java b/core/tests/coretests/src/android/view/VisibilityCallback.java
index f98a0a8..c965973 100644
--- a/core/tests/coretests/src/android/view/VisibilityCallback.java
+++ b/core/tests/coretests/src/android/view/VisibilityCallback.java
@@ -16,16 +16,15 @@
 
 package android.view;
 
+import android.app.Activity;
 import android.content.Context;
+import android.os.Bundle;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.widget.TextView;
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.widget.Button;
-import android.view.View;
-import android.app.Activity;
+import android.widget.TextView;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercise View's ability to change their visibility: GONE, INVISIBLE and
diff --git a/core/tests/coretests/src/android/view/VisibilityCallbackTest.java b/core/tests/coretests/src/android/view/VisibilityCallbackTest.java
index ec956d2..d7c7b4c 100644
--- a/core/tests/coretests/src/android/view/VisibilityCallbackTest.java
+++ b/core/tests/coretests/src/android/view/VisibilityCallbackTest.java
@@ -17,12 +17,12 @@
 package android.view;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
-import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.TextView;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/VisibilityTest.java b/core/tests/coretests/src/android/view/VisibilityTest.java
index 29c1c8a..83a7702 100644
--- a/core/tests/coretests/src/android/view/VisibilityTest.java
+++ b/core/tests/coretests/src/android/view/VisibilityTest.java
@@ -20,11 +20,12 @@
 import static android.view.KeyEvent.KEYCODE_DPAD_LEFT;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.Button;
 import android.widget.TextView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java
index 1513a1a..15a96a1 100644
--- a/core/tests/coretests/src/android/view/WindowInsetsTest.java
+++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java
@@ -17,18 +17,18 @@
 package android.view;
 
 import static android.view.WindowInsets.Type.ime;
-import static android.view.WindowInsets.Type.indexOf;
 import static android.view.WindowInsets.Type.sideBars;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowInsets.Builder;
-import android.view.WindowInsets.Type;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/ZeroSized.java b/core/tests/coretests/src/android/view/ZeroSized.java
index f2a6b3e..9e2dfcb 100644
--- a/core/tests/coretests/src/android/view/ZeroSized.java
+++ b/core/tests/coretests/src/android/view/ZeroSized.java
@@ -16,10 +16,10 @@
 
 package android.view;
 
-import com.android.frameworks.coretests.R;
-
-import android.os.Bundle;
 import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * This activity contains Views with various widths and heights. The goal is to exercise the
diff --git a/core/tests/coretests/src/android/view/ZeroSizedTest.java b/core/tests/coretests/src/android/view/ZeroSizedTest.java
index 193fc98..946bf68 100644
--- a/core/tests/coretests/src/android/view/ZeroSizedTest.java
+++ b/core/tests/coretests/src/android/view/ZeroSizedTest.java
@@ -16,13 +16,12 @@
 
 package android.view;
 
-import android.view.ZeroSized;
-import com.android.frameworks.coretests.R;
-
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
 import android.graphics.Bitmap;
+import android.test.ActivityInstrumentationTestCase;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Builds the drawing cache of Views of various dimension. The assumption is that
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 7f675ff..a88968b 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -28,10 +28,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
index 3e03414..46c96c9 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityEventTest.java
@@ -21,7 +21,8 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index 318d122..ab24f89 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -22,10 +22,12 @@
 
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import libcore.util.EmptyArray;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index 506e544..0ed690c 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -25,11 +25,12 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.CollectionUtils;
 
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
index 4814c61..11f4e3c 100644
--- a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
@@ -14,7 +14,7 @@
 
 package android.view.accessibility;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
index 7619af2..33bc593 100644
--- a/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
+++ b/core/tests/coretests/src/android/view/autofill/AutofillIdTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.autofill;
 
 import static com.google.common.truth.Truth.assertThat;
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index 73cceae..6ecb63a 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.contentcapture;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -114,7 +115,7 @@
         }
 
         @Override
-        void flush() {
+        void flush(int reason) {
             throw new UnsupportedOperationException("should not have been called");
         }
 
diff --git a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
index bbfe01c..099f41d 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.contentcapture;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -24,7 +25,6 @@
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
 import android.view.View;
 import android.view.ViewStructure.HtmlInfo;
 import android.view.autofill.AutofillId;
@@ -32,6 +32,8 @@
 import android.view.contentcapture.ViewNode.ViewStructureImpl;
 import android.widget.FrameLayout;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
diff --git a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
index 0fd0136..ace6611 100644
--- a/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/CursorAnchorInfoTest.java
@@ -28,11 +28,12 @@
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.TextUtils;
 import android.view.inputmethod.CursorAnchorInfo.Builder;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index 1b00e09..f24e232 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -26,9 +26,10 @@
 import android.content.pm.ServiceInfo;
 import android.os.Bundle;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java
index 55e5e36..9f259a8 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java
@@ -20,11 +20,12 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowManager;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
index 8df1848..e2fb46a 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeArrayTest.java
@@ -19,10 +19,11 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java
index c76359e..1e0e1235 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodSubtypeTest.java
@@ -23,10 +23,11 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java b/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java
index 8c96b58..453ad72 100644
--- a/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/SparseRectFArrayTest.java
@@ -23,10 +23,11 @@
 
 import android.graphics.RectF;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
index 657a7fc..ba85d76 100644
--- a/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
+++ b/core/tests/coretests/src/android/view/menu/ContextMenuTest.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.graphics.Point;
-import android.support.test.filters.MediumTest;
 import android.test.ActivityInstrumentationTestCase;
 import android.util.PollingCheck;
 import android.view.Display;
@@ -26,6 +25,8 @@
 import android.view.WindowManager;
 import android.widget.espresso.ContextMenuUtils;
 
+import androidx.test.filters.MediumTest;
+
 @MediumTest
 public class ContextMenuTest extends ActivityInstrumentationTestCase<ContextMenuActivity> {
 
diff --git a/core/tests/coretests/src/android/view/menu/MenuLayout.java b/core/tests/coretests/src/android/view/menu/MenuLayout.java
index 356c948..33ee515 100644
--- a/core/tests/coretests/src/android/view/menu/MenuLayout.java
+++ b/core/tests/coretests/src/android/view/menu/MenuLayout.java
@@ -16,8 +16,6 @@
 
 package android.view.menu;
 
-import android.view.menu.MenuScenario.Params;
-
 import android.os.Bundle;
 import android.view.Menu;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/view/menu/MenuLayoutLandscapeTest.java b/core/tests/coretests/src/android/view/menu/MenuLayoutLandscapeTest.java
index 8ed0d86..ff9f166 100644
--- a/core/tests/coretests/src/android/view/menu/MenuLayoutLandscapeTest.java
+++ b/core/tests/coretests/src/android/view/menu/MenuLayoutLandscapeTest.java
@@ -16,13 +16,10 @@
 
 package android.view.menu;
 
-import android.util.KeyUtils;
-import com.android.internal.view.menu.IconMenuView;
-import com.android.internal.view.menu.MenuBuilder;
-
-import android.content.pm.ActivityInfo;
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase;
+import android.util.KeyUtils;
+
+import androidx.test.filters.LargeTest;
 
 @LargeTest
 public class MenuLayoutLandscapeTest extends ActivityInstrumentationTestCase<MenuLayoutLandscape> {
diff --git a/core/tests/coretests/src/android/view/menu/MenuLayoutPortraitTest.java b/core/tests/coretests/src/android/view/menu/MenuLayoutPortraitTest.java
index ccf1264..360be53 100644
--- a/core/tests/coretests/src/android/view/menu/MenuLayoutPortraitTest.java
+++ b/core/tests/coretests/src/android/view/menu/MenuLayoutPortraitTest.java
@@ -16,11 +16,11 @@
 
 package android.view.menu;
 
-import android.content.pm.ActivityInfo;
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase;
 import android.util.KeyUtils;
 
+import androidx.test.filters.LargeTest;
+
 @LargeTest
 public class MenuLayoutPortraitTest extends ActivityInstrumentationTestCase<MenuLayoutPortrait> {
     private static final String LONG_TITLE = "Really really really really really really really really really really long title";
diff --git a/core/tests/coretests/src/android/view/menu/MenuWith1ItemTest.java b/core/tests/coretests/src/android/view/menu/MenuWith1ItemTest.java
index 82ad858..c18e361 100644
--- a/core/tests/coretests/src/android/view/menu/MenuWith1ItemTest.java
+++ b/core/tests/coretests/src/android/view/menu/MenuWith1ItemTest.java
@@ -16,17 +16,12 @@
 
 package android.view.menu;
 
-import android.view.menu.MenuWith1Item;
-import android.util.KeyUtils;
-import com.android.internal.view.menu.MenuBuilder;
-
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.TouchUtils;
-
 import android.test.ActivityInstrumentationTestCase;
+import android.util.KeyUtils;
 import android.view.KeyEvent;
-import android.view.View;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 public class MenuWith1ItemTest extends ActivityInstrumentationTestCase<MenuWith1Item> {
     private MenuWith1Item mActivity;
diff --git a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
index 4a6c093..780e15a 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ActionsSuggestionsHelperTest.java
@@ -22,8 +22,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Person;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.android.textclassifier.ActionsSuggestionsModel;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java b/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
index 0180856..fef6583 100644
--- a/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
+++ b/core/tests/coretests/src/android/view/textclassifier/FakeContextBuilder.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -29,9 +30,8 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.support.test.InstrumentationRegistry;
 
-import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
 
 import com.google.common.base.Preconditions;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/IntentFactoryTest.java b/core/tests/coretests/src/android/view/textclassifier/IntentFactoryTest.java
index aaadefb..3fc8e4c 100644
--- a/core/tests/coretests/src/android/view/textclassifier/IntentFactoryTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/IntentFactoryTest.java
@@ -13,14 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.textclassifier;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.google.android.textclassifier.AnnotatorModel;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
index 88d162b..74b8e3b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.textclassifier;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -20,9 +21,10 @@
 import static org.mockito.Mockito.when;
 
 import android.os.LocaleList;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
index a3c6179..46e3a4c 100644
--- a/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/SelectionEventTest.java
@@ -19,8 +19,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
index 54007fb..9662182 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java
@@ -20,8 +20,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index a3f69d9..4fcd51c 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -26,9 +26,10 @@
 import android.content.Intent;
 import android.os.LocaleList;
 import android.service.textclassifier.TextClassifierService;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index aaf7312..99c959e 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -32,11 +32,12 @@
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index ec6101c..7009fb2 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -24,11 +24,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.LocaleList;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
 import android.text.Spannable;
 import android.text.SpannableString;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLanguageTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLanguageTest.java
index 1dcaed6..d0d32e3 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLanguageTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLanguageTest.java
@@ -21,8 +21,9 @@
 import android.icu.util.ULocale;
 import android.os.Bundle;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index f022d04..b9cc8f4 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -21,10 +21,11 @@
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index 2ea49f7..30cc4e8 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -21,8 +21,9 @@
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
index 8e4f02c..5e8e582 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/GenerateLinksLoggerTest.java
@@ -23,13 +23,14 @@
 import static org.mockito.Mockito.mock;
 
 import android.metrics.LogMaker;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 import android.view.textclassifier.GenerateLinksLogger;
 import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
index 0597a89..b1b7416 100644
--- a/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/TextClassifierEventTronLoggerTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.view.textclassifier.logging;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE;
@@ -24,13 +25,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.metrics.LogMaker;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.textclassifier.ConversationAction;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassifierEvent;
 import android.view.textclassifier.TextClassifierEventTronLogger;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.logging.MetricsLogger;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/view/textservice/SpellCheckerSubtypeTest.java b/core/tests/coretests/src/android/view/textservice/SpellCheckerSubtypeTest.java
index 4a1c414..638d894 100644
--- a/core/tests/coretests/src/android/view/textservice/SpellCheckerSubtypeTest.java
+++ b/core/tests/coretests/src/android/view/textservice/SpellCheckerSubtypeTest.java
@@ -16,15 +16,16 @@
 
 package android.view.textservice;
 
+import static android.test.MoreAsserts.assertNotEqual;
+
 import android.os.Parcel;
 import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import java.util.Arrays;
 import java.util.Locale;
 
-import static android.test.MoreAsserts.assertNotEqual;
-
 /**
  * TODO: Most of part can be, and probably should be, moved to CTS.
  */
diff --git a/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java b/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java
index 4f31c4e..6edc162 100644
--- a/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java
+++ b/core/tests/coretests/src/android/widget/AppWidgetHostViewTest.java
@@ -24,18 +24,14 @@
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 import android.view.ViewGroup.OnHierarchyChangeListener;
 
-import com.android.frameworks.coretests.R;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
-import java.util.ArrayList;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Future;
+import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -43,6 +39,11 @@
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+
 /**
  * Tests for AppWidgetHostView
  */
diff --git a/core/tests/coretests/src/android/widget/AutoCompleteTextViewCallbacks.java b/core/tests/coretests/src/android/widget/AutoCompleteTextViewCallbacks.java
index 8e73b52..01e82a5 100644
--- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewCallbacks.java
+++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewCallbacks.java
@@ -18,7 +18,8 @@
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.FlakyTest;
+
+import androidx.test.filters.FlakyTest;
 
 // TODO: tests fail intermittently. Add back MediumTest annotation when fixed
 public class AutoCompleteTextViewCallbacks
@@ -32,7 +33,7 @@
 
     /** Test that the initial popup of the suggestions does not select anything.
      */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupNoSelection() throws Exception {
         AutoCompleteTextViewSimple theActivity = getActivity();
         AutoCompleteTextView textView = theActivity.getTextView();
@@ -57,7 +58,7 @@
     }
 
     /** Test that arrow-down into the popup calls the onSelected callback. */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupEnterSelection() throws Exception {
         final AutoCompleteTextViewSimple theActivity = getActivity();
         AutoCompleteTextView textView = theActivity.getTextView();
@@ -106,7 +107,7 @@
     }
 
     /** Test that arrow-up out of the popup calls the onNothingSelected callback */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupLeaveSelection() {
         final AutoCompleteTextViewSimple theActivity = getActivity();
         AutoCompleteTextView textView = theActivity.getTextView();
diff --git a/core/tests/coretests/src/android/widget/AutoCompleteTextViewPopup.java b/core/tests/coretests/src/android/widget/AutoCompleteTextViewPopup.java
index ee0abae..21e4184 100644
--- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewPopup.java
+++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewPopup.java
@@ -18,8 +18,8 @@
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.FlakyTest;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.FlakyTest;
 
 /**
  * A collection of tests on aspects of the AutoCompleteTextView's popup
@@ -41,7 +41,7 @@
     }
 
     /** Test that we can move the selection and it responds as expected */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupSetListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
         final AutoCompleteTextView textView = theActivity.getTextView();
@@ -73,7 +73,7 @@
     }
 
     /** Test that we can look at the selection as we move around */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupGetListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
         final AutoCompleteTextView textView = theActivity.getTextView();
@@ -100,7 +100,7 @@
     }
 
     /** Test that we can clear the selection */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupClearListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
         final AutoCompleteTextView textView = theActivity.getTextView();
@@ -133,7 +133,7 @@
     }
 
     /** Make sure we handle an empty adapter properly */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupNavigateNoAdapter() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
         final AutoCompleteTextView textView = theActivity.getTextView();
@@ -167,7 +167,7 @@
     }
 
     /** Test the show/hide behavior of the drop-down. */
-    @FlakyTest(tolerance=3)
+    @FlakyTest
     public void testPopupShow() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
         final AutoCompleteTextView textView = theActivity.getTextView();
diff --git a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
index b4e05aa..063bec5 100644
--- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
+++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.util.Log;
@@ -25,6 +23,8 @@
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 
+import com.android.frameworks.coretests.R;
+
 public class AutoCompleteTextViewSimple extends Activity 
         implements OnItemClickListener, OnItemSelectedListener {
 
diff --git a/core/tests/coretests/src/android/widget/DatePickerActivity.java b/core/tests/coretests/src/android/widget/DatePickerActivity.java
index c3b25a1..9e455b2 100644
--- a/core/tests/coretests/src/android/widget/DatePickerActivity.java
+++ b/core/tests/coretests/src/android/widget/DatePickerActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/DatePickerFocusTest.java b/core/tests/coretests/src/android/widget/DatePickerFocusTest.java
index be85450..f067230 100644
--- a/core/tests/coretests/src/android/widget/DatePickerFocusTest.java
+++ b/core/tests/coretests/src/android/widget/DatePickerFocusTest.java
@@ -19,11 +19,12 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.os.SystemClock;
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.KeyEvent;
 import android.view.View;
 
+import androidx.test.filters.LargeTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/DateTimeViewTest.java b/core/tests/coretests/src/android/widget/DateTimeViewTest.java
index 40a6b7a..d0bd4b8 100644
--- a/core/tests/coretests/src/android/widget/DateTimeViewTest.java
+++ b/core/tests/coretests/src/android/widget/DateTimeViewTest.java
@@ -16,10 +16,10 @@
 
 package android.widget;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/widget/EditorCursorTest.java b/core/tests/coretests/src/android/widget/EditorCursorTest.java
index 9186827b..e4f55df 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorTest.java
@@ -31,10 +31,11 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/widget/ListViewTest.java b/core/tests/coretests/src/android/widget/ListViewTest.java
index 449b696..254af2a 100644
--- a/core/tests/coretests/src/android/widget/ListViewTest.java
+++ b/core/tests/coretests/src/android/widget/ListViewTest.java
@@ -16,20 +16,19 @@
 
 package android.widget;
 
-import android.test.suitebuilder.annotation.Suppress;
-import com.google.android.collect.Lists;
-
-import junit.framework.Assert;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.InstrumentationTestCase;
 import android.test.mock.MockContext;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
+import com.google.android.collect.Lists;
+
+import junit.framework.Assert;
 
 import java.util.List;
 
diff --git a/core/tests/coretests/src/android/widget/RadioGroupActivity.java b/core/tests/coretests/src/android/widget/RadioGroupActivity.java
index c87aa3a..dd3b30a 100644
--- a/core/tests/coretests/src/android/widget/RadioGroupActivity.java
+++ b/core/tests/coretests/src/android/widget/RadioGroupActivity.java
@@ -17,11 +17,11 @@
 
 package android.widget;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class RadioGroupActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/core/tests/coretests/src/android/widget/RadioGroupPreCheckedTest.java b/core/tests/coretests/src/android/widget/RadioGroupPreCheckedTest.java
index 1ab3628..18c1ea1 100644
--- a/core/tests/coretests/src/android/widget/RadioGroupPreCheckedTest.java
+++ b/core/tests/coretests/src/android/widget/RadioGroupPreCheckedTest.java
@@ -16,12 +16,13 @@
 
 package android.widget;
 
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercises {@link android.widget.RadioGroup}'s check feature.
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsAdapterTest.java b/core/tests/coretests/src/android/widget/RemoteViewsAdapterTest.java
index 06b860a..da53f6d 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsAdapterTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsAdapterTest.java
@@ -38,11 +38,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 import com.android.internal.widget.IRemoteViewsFactory;
 
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 36792bb..8cb7e1b 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -32,12 +32,13 @@
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
index 2add221..74aad9a 100644
--- a/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
+++ b/core/tests/coretests/src/android/widget/SelectionActionModeHelperTest.java
@@ -22,7 +22,8 @@
 
 import android.graphics.PointF;
 import android.graphics.RectF;
-import android.support.test.filters.LargeTest;
+
+import androidx.test.filters.LargeTest;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java b/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
index 1731c08..a79b30d 100644
--- a/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
+++ b/core/tests/coretests/src/android/widget/SimpleCursorAdapterTest.java
@@ -16,14 +16,15 @@
 
 package android.widget;
 
-import android.test.suitebuilder.annotation.Suppress;
-import com.google.android.collect.Lists;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
+
+import com.google.android.collect.Lists;
 
 import java.util.ArrayList;
 import java.util.Random;
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index eafe427..483270e 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -36,13 +36,13 @@
 import static android.widget.espresso.SuggestionsPopupwindowUtils.onSuggestionsPopup;
 import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
 import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
+
 import static org.hamcrest.Matchers.is;
+
 import android.content.res.TypedArray;
 import android.support.test.espresso.NoMatchingViewException;
 import android.support.test.espresso.ViewAssertion;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.Spanned;
@@ -51,6 +51,8 @@
 import android.text.style.TextAppearanceSpan;
 import android.view.View;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index ff4a7da..41fa08b 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -43,14 +43,15 @@
 import static android.widget.espresso.TextViewAssertions.hasSelection;
 
 import android.app.Activity;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.Suppress;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.MotionEvent;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 90758ba..9d93421 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -27,10 +27,8 @@
 import static android.support.test.espresso.matcher.ViewMatchers.withText;
 import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates;
 import static android.widget.espresso.DragHandleUtils.onHandleView;
-import static android.widget.espresso.FloatingToolbarEspressoUtils
-        .assertFloatingToolbarContainsItem;
-import static android.widget.espresso.FloatingToolbarEspressoUtils
-        .assertFloatingToolbarDoesNotContainItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.clickFloatingToolbarItem;
@@ -62,13 +60,8 @@
 import android.app.Instrumentation;
 import android.content.ClipData;
 import android.content.ClipboardManager;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.action.EspressoKey;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
-import android.test.suitebuilder.annotation.Suppress;
 import android.text.InputType;
 import android.text.Selection;
 import android.text.Spannable;
@@ -85,6 +78,12 @@
 import android.view.textclassifier.TextLinksParams;
 import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java b/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java
index e9d1d3e..113db9d 100644
--- a/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewFallbackLineSpacingTest.java
@@ -21,8 +21,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.app.Activity;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
 import android.text.DynamicLayout;
 import android.text.FontFallbackSetup;
 import android.text.Layout;
@@ -31,6 +29,9 @@
 import android.view.View;
 import android.widget.TextView.BufferType;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java b/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java
index cf173fb..a769ea4 100644
--- a/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewPerformanceTest.java
@@ -20,14 +20,15 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.SpannedString;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 1c5610b..585360f 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -27,11 +27,6 @@
 import android.content.Intent;
 import android.graphics.Paint;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.MediumTest;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.GetChars;
 import android.text.Layout;
 import android.text.PrecomputedText;
@@ -40,6 +35,12 @@
 import android.view.View;
 import android.widget.TextView.BufferType;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java b/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
index 75da6fe..85a4509 100644
--- a/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
+++ b/core/tests/coretests/src/android/widget/focus/AdjacentVerticalRectLists.java
@@ -16,12 +16,11 @@
 
 package android.widget.focus;
 
-import android.util.InternalSelectionView;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.LinearLayout;
+import android.util.InternalSelectionView;
 import android.view.ViewGroup;
+import android.widget.LinearLayout;
 
 /**
  * {@link android.view.FocusFinder#findNextFocus(android.view.ViewGroup, android.view.View, int)}
diff --git a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
index f6b0520..fe6d3c8 100644
--- a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
+++ b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
@@ -16,13 +16,13 @@
 
 package android.widget.focus;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.ViewGroup;
 import android.widget.Button;
 
+import com.android.frameworks.coretests.R;
+
 public class DescendantFocusability extends Activity {
 
     public ViewGroup beforeDescendants;
diff --git a/core/tests/coretests/src/android/widget/focus/DescendantFocusabilityTest.java b/core/tests/coretests/src/android/widget/focus/DescendantFocusabilityTest.java
index 2af42ac..1c570df 100644
--- a/core/tests/coretests/src/android/widget/focus/DescendantFocusabilityTest.java
+++ b/core/tests/coretests/src/android/widget/focus/DescendantFocusabilityTest.java
@@ -16,15 +16,14 @@
 
 package android.widget.focus;
 
-import android.widget.focus.DescendantFocusability;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.UiThreadTest;
 import android.test.TouchUtils;
 import android.view.ViewGroup;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class DescendantFocusabilityTest extends ActivityInstrumentationTestCase<DescendantFocusability> {
 
     private DescendantFocusability a;
diff --git a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
index b3d5ec5..0cb80ce 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
@@ -16,13 +16,13 @@
 
 package android.widget.focus;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.LinearLayout;
-import android.widget.Button;
 import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Exercises cases where elements of the UI are removed (and
diff --git a/core/tests/coretests/src/android/widget/focus/FocusAfterRemovalTest.java b/core/tests/coretests/src/android/widget/focus/FocusAfterRemovalTest.java
index a1b7bcb..6c46d08 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusAfterRemovalTest.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusAfterRemovalTest.java
@@ -16,15 +16,15 @@
 
 package android.widget.focus;
 
-import android.widget.focus.FocusAfterRemoval;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.Button;
-import android.widget.LinearLayout;
 import android.view.KeyEvent;
 import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * {@link FocusAfterRemoval} is set up to exercise cases where the views that
diff --git a/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java b/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
index 8f8f184..26dc233 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusChangeWithInterestingRectHintTest.java
@@ -16,14 +16,13 @@
 
 package android.widget.focus;
 
-import android.widget.focus.AdjacentVerticalRectLists;
-import android.util.InternalSelectionView;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.util.InternalSelectionView;
 import android.view.KeyEvent;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * {@link android.view.FocusFinder#findNextFocus(android.view.ViewGroup, android.view.View, int)}
  * and
diff --git a/core/tests/coretests/src/android/widget/focus/GoneParentFocusedChildTest.java b/core/tests/coretests/src/android/widget/focus/GoneParentFocusedChildTest.java
index dcbddef..b7974e3 100644
--- a/core/tests/coretests/src/android/widget/focus/GoneParentFocusedChildTest.java
+++ b/core/tests/coretests/src/android/widget/focus/GoneParentFocusedChildTest.java
@@ -17,10 +17,10 @@
 package android.widget.focus;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.view.View;
-import android.widget.focus.GoneParentFocusedChild;
+
+import androidx.test.filters.MediumTest;
 
 /**
  * When a parent is GONE, key events shouldn't go to its children, even if they
diff --git a/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearch.java b/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearch.java
index 11cac1e..aab9119 100644
--- a/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearch.java
+++ b/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearch.java
@@ -17,12 +17,12 @@
 package android.widget.focus;
 
 import android.app.Activity;
-import android.widget.LinearLayout;
-import android.widget.Button;
-import android.widget.TextView;
+import android.content.Context;
 import android.os.Bundle;
 import android.view.ViewGroup;
-import android.content.Context;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 public class HorizontalFocusSearch extends Activity {
 
diff --git a/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearchTest.java b/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearchTest.java
index 43986ee..855a3219 100644
--- a/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearchTest.java
+++ b/core/tests/coretests/src/android/widget/focus/HorizontalFocusSearchTest.java
@@ -16,18 +16,17 @@
 
 package android.widget.focus;
 
-import android.widget.focus.HorizontalFocusSearch;
-
-import android.support.test.filters.LargeTest;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.LinearLayout;
-import android.widget.Button;
-import android.view.View;
-
 import static android.widget.focus.VerticalFocusSearchTest.FocusSearchAlg;
 import static android.widget.focus.VerticalFocusSearchTest.NewFocusSearchAlg;
 
+import android.test.ActivityInstrumentationTestCase;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.Suppress;
+
 /**
  * Tests that focus searching works on a horizontal linear layout of buttons of
  * various widths and vertical placements.
diff --git a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
index acd632f..ec234bc 100644
--- a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
+++ b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
@@ -21,6 +21,7 @@
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.LinearLayout;
+
 import com.android.frameworks.coretests.R;
 
 public class LinearLayoutGrid extends Activity {
diff --git a/core/tests/coretests/src/android/widget/focus/LinearLayoutGridTest.java b/core/tests/coretests/src/android/widget/focus/LinearLayoutGridTest.java
index 89cb8bb..c81317c 100644
--- a/core/tests/coretests/src/android/widget/focus/LinearLayoutGridTest.java
+++ b/core/tests/coretests/src/android/widget/focus/LinearLayoutGridTest.java
@@ -17,11 +17,11 @@
 package android.widget.focus;
 
 import android.test.SingleLaunchActivityTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.FocusFinder;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.focus.LinearLayoutGrid;
+
+import androidx.test.filters.MediumTest;
 
 /**
  * Tests focus searching between buttons within a grid that are touching, for example,
diff --git a/core/tests/coretests/src/android/widget/focus/ListOfButtons.java b/core/tests/coretests/src/android/widget/focus/ListOfButtons.java
index 308861d..5663ed2 100644
--- a/core/tests/coretests/src/android/widget/focus/ListOfButtons.java
+++ b/core/tests/coretests/src/android/widget/focus/ListOfButtons.java
@@ -16,8 +16,6 @@
 
 package android.widget.focus;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.os.Bundle;
@@ -26,6 +24,8 @@
 import android.widget.ArrayAdapter;
 import android.widget.Button;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * A layout with a ListView containing buttons.
  */
diff --git a/core/tests/coretests/src/android/widget/focus/ListOfButtonsTest.java b/core/tests/coretests/src/android/widget/focus/ListOfButtonsTest.java
index bec6f80..4cf4a3a 100644
--- a/core/tests/coretests/src/android/widget/focus/ListOfButtonsTest.java
+++ b/core/tests/coretests/src/android/widget/focus/ListOfButtonsTest.java
@@ -16,17 +16,17 @@
 
 package android.widget.focus;
 
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.focus.ListOfButtons;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListAdapter;
-import android.widget.Button;
-import android.widget.ListView;
 import android.view.KeyEvent;
 import android.view.View;
+import android.widget.Button;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * Tests that focus works as expected when navigating into and out of
diff --git a/core/tests/coretests/src/android/widget/focus/ListOfEditTexts.java b/core/tests/coretests/src/android/widget/focus/ListOfEditTexts.java
index c2e7a26..936c999 100644
--- a/core/tests/coretests/src/android/widget/focus/ListOfEditTexts.java
+++ b/core/tests/coretests/src/android/widget/focus/ListOfEditTexts.java
@@ -21,7 +21,12 @@
 import android.os.Bundle;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.*;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
 import com.google.android.collect.Lists;
 
 import java.util.List;
diff --git a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
index 53b866c..73e4ea8 100644
--- a/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
+++ b/core/tests/coretests/src/android/widget/focus/ListOfInternalSelectionViews.java
@@ -19,11 +19,11 @@
 import android.app.Activity;
 import android.graphics.Point;
 import android.os.Bundle;
+import android.util.InternalSelectionView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ListView;
-import android.util.InternalSelectionView;
 
 /**
  * A list of {@link InternalSelectionView}s paramatarized by the number of items,
diff --git a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
index b908201..8accf21 100644
--- a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
+++ b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
@@ -27,9 +27,10 @@
 import android.widget.Button;
 import android.widget.TextView;
 
-import com.google.android.collect.Lists;
 import com.android.frameworks.coretests.R;
 
+import com.google.android.collect.Lists;
+
 import java.util.List;
 
 public class ListWithFooterViewAndNewLabels extends ListActivity {
diff --git a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabelsTest.java b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabelsTest.java
index 57dbb78..d0fcde5 100644
--- a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabelsTest.java
+++ b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabelsTest.java
@@ -16,14 +16,13 @@
 
 package android.widget.focus;
 
-import android.widget.focus.ListWithFooterViewAndNewLabels;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
 import android.widget.Button;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 
+import com.android.frameworks.coretests.R;
+
 public class ListWithFooterViewAndNewLabelsTest
         extends ActivityInstrumentationTestCase<ListWithFooterViewAndNewLabels> {
 
diff --git a/core/tests/coretests/src/android/widget/focus/ListWithMailMessages.java b/core/tests/coretests/src/android/widget/focus/ListWithMailMessages.java
index 5c891f9..50a8614 100644
--- a/core/tests/coretests/src/android/widget/focus/ListWithMailMessages.java
+++ b/core/tests/coretests/src/android/widget/focus/ListWithMailMessages.java
@@ -16,19 +16,20 @@
 
 package android.widget.focus;
 
-import com.android.frameworks.coretests.R;
-import com.google.android.collect.Lists;
-
 import android.app.ListActivity;
+import android.content.Context;
 import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
 import android.widget.ArrayAdapter;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.webkit.WebView;
+
+import com.android.frameworks.coretests.R;
+
+import com.google.android.collect.Lists;
 
 import java.util.List;
 
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocus.java b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
index 4daf0b4..5042efd 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocus.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
@@ -16,13 +16,13 @@
 
 package android.widget.focus;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.Handler;
 import android.widget.Button;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercises cases where elements of the UI are requestFocus()ed.
  */
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
index cdfa217..bc770c5 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocusTest.java
@@ -21,16 +21,18 @@
 
 import android.os.Handler;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.AndroidRuntimeException;
 import android.view.View;
 import android.view.View.OnFocusChangeListener;
 import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
 import android.widget.Button;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
+
 import org.mockito.InOrder;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java b/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
index 06cb75d..e6e76cc 100644
--- a/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
+++ b/core/tests/coretests/src/android/widget/focus/ScrollingThroughListOfFocusablesTest.java
@@ -18,12 +18,12 @@
 
 import android.graphics.Rect;
 import android.test.InstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.InternalSelectionView;
 import android.view.KeyEvent;
 import android.widget.ListView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 /**
  * TODO: extract base test case that launches {@link ListOfInternalSelectionViews} with
diff --git a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
index 4a809e0..2ca9f6d 100644
--- a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
+++ b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearch.java
@@ -17,13 +17,13 @@
 package android.widget.focus;
 
 import android.app.Activity;
+import android.content.Context;
 import android.os.Bundle;
-import android.widget.LinearLayout;
-import android.widget.Button;
-import android.widget.TextView;
 import android.view.Gravity;
 import android.view.ViewGroup;
-import android.content.Context;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 /**
  * Holds a few buttons of various sizes and horizontal placements in a
diff --git a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearchTest.java b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearchTest.java
index f01422e..319756c 100644
--- a/core/tests/coretests/src/android/widget/focus/VerticalFocusSearchTest.java
+++ b/core/tests/coretests/src/android/widget/focus/VerticalFocusSearchTest.java
@@ -16,17 +16,16 @@
 
 package android.widget.focus;
 
-import android.widget.focus.VerticalFocusSearch;
-
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.FocusFinder;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.Suppress;
+
 /**
  * Tests that focus searching works on a vertical linear layout of buttons of
  * various widths and horizontal placements.
diff --git a/core/tests/coretests/src/android/widget/gridview/GridDelete.java b/core/tests/coretests/src/android/widget/gridview/GridDelete.java
index 57ae8f39..b040f69 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridDelete.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridDelete.java
@@ -16,6 +16,7 @@
 
 package android.widget.gridview;
 
+import android.util.GridScenario;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -23,8 +24,6 @@
 import android.widget.GridView;
 import android.widget.ListAdapter;
 
-import android.util.GridScenario;
-
 import java.util.ArrayList;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/gridview/GridInHorizontalTest.java b/core/tests/coretests/src/android/widget/gridview/GridInHorizontalTest.java
index 21ca655..5247009 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridInHorizontalTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridInHorizontalTest.java
@@ -17,10 +17,9 @@
 package android.widget.gridview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.GridView;
 
-import android.widget.gridview.GridInHorizontal;
+import androidx.test.filters.MediumTest;
 
 public class GridInHorizontalTest extends ActivityInstrumentationTestCase<GridInHorizontal> {
 
diff --git a/core/tests/coretests/src/android/widget/gridview/GridInVerticalTest.java b/core/tests/coretests/src/android/widget/gridview/GridInVerticalTest.java
index a674db2..290f70e 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridInVerticalTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridInVerticalTest.java
@@ -17,10 +17,9 @@
 package android.widget.gridview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.GridView;
 
-import android.widget.gridview.GridInVertical;
+import androidx.test.filters.MediumTest;
 
 public class GridInVerticalTest extends ActivityInstrumentationTestCase<GridInVertical> {
 
diff --git a/core/tests/coretests/src/android/widget/gridview/GridPaddingTest.java b/core/tests/coretests/src/android/widget/gridview/GridPaddingTest.java
index ecd4b1c..d2ae7cf 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridPaddingTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridPaddingTest.java
@@ -17,9 +17,10 @@
 package android.widget.gridview;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.GridView;
 
+import androidx.test.filters.MediumTest;
+
 public class GridPaddingTest extends ActivityInstrumentationTestCase2<GridPadding> {
     private GridView mGridView;
 
diff --git a/core/tests/coretests/src/android/widget/gridview/GridScrollListenerTest.java b/core/tests/coretests/src/android/widget/gridview/GridScrollListenerTest.java
index 53eeb48..466c55f 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridScrollListenerTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridScrollListenerTest.java
@@ -19,12 +19,13 @@
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.AbsListView;
 import android.widget.GridView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class GridScrollListenerTest extends ActivityInstrumentationTestCase<GridScrollListener> implements
         AbsListView.OnScrollListener {
     private GridScrollListener mActivity;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
index 0e362b6..db4f2dc 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionBaseTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.gridview;
 
-import android.util.GridScenario;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
+import android.util.GridScenario;
 import android.widget.GridView;
 
+import androidx.test.filters.MediumTest;
+
 public class GridSetSelectionBaseTest<T extends GridScenario> extends ActivityInstrumentationTestCase<T> {
     private T mActivity;
     private GridView mGridView;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionManyTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionManyTest.java
index 6739645..17a6044 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionManyTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionManyTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridSetSelectionMany;
-
 public class GridSetSelectionManyTest extends GridSetSelectionBaseTest<GridSetSelectionMany> {
     public GridSetSelectionManyTest() {
         super(GridSetSelectionMany.class);
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomManyTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomManyTest.java
index 46922b97..a71f732 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomManyTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomManyTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridSetSelectionStackFromBottomMany;
-
 public class GridSetSelectionStackFromBottomManyTest extends GridSetSelectionBaseTest<GridSetSelectionStackFromBottomMany> {
     public GridSetSelectionStackFromBottomManyTest() {
         super(GridSetSelectionStackFromBottomMany.class);
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomTest.java
index 67dd6f1..4e6e8aa 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionStackFromBottomTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridSetSelectionStackFromBottom;
-
 public class GridSetSelectionStackFromBottomTest extends GridSetSelectionBaseTest<GridSetSelectionStackFromBottom> {
     public GridSetSelectionStackFromBottomTest() {
         super(GridSetSelectionStackFromBottom.class);
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionTest.java b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionTest.java
index 2127b3c..68802fe 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSetSelectionTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSetSelectionTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridSetSelection;
-
 public class GridSetSelectionTest extends GridSetSelectionBaseTest<GridSetSelection> {
     public GridSetSelectionTest() {
         super(GridSetSelection.class);
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSimple.java b/core/tests/coretests/src/android/widget/gridview/GridSimple.java
index 7c2c696..67bb751 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSimple.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSimple.java
@@ -18,12 +18,11 @@
 
 import android.graphics.drawable.PaintDrawable;
 import android.os.Bundle;
+import android.util.GridScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 
-import android.util.GridScenario;
-
 public class GridSimple extends GridScenario {
     @Override
     protected void init(Params params) {
diff --git a/core/tests/coretests/src/android/widget/gridview/GridSingleColumnTest.java b/core/tests/coretests/src/android/widget/gridview/GridSingleColumnTest.java
index 3b2504e..0f67522 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridSingleColumnTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridSingleColumnTest.java
@@ -17,10 +17,9 @@
 package android.widget.gridview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.GridView;
 
-import android.widget.gridview.GridSingleColumn;
+import androidx.test.filters.MediumTest;
 
 public class GridSingleColumnTest extends ActivityInstrumentationTestCase<GridSingleColumn> {
     private GridSingleColumn mActivity;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomManyTest.java b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomManyTest.java
index 640737e..a369616 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomManyTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomManyTest.java
@@ -16,11 +16,10 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridStackFromBottomMany;
-
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.GridView;
 import android.test.ActivityInstrumentationTestCase;
+import android.widget.GridView;
+
+import androidx.test.filters.MediumTest;
 
 public class GridStackFromBottomManyTest extends ActivityInstrumentationTestCase<GridStackFromBottomMany> {
     private GridStackFromBottomMany mActivity;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomTest.java b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomTest.java
index 8fec241..da1b638 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridStackFromBottomTest.java
@@ -16,12 +16,11 @@
 
 package android.widget.gridview;
 
-import android.widget.gridview.GridStackFromBottom;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.GridView;
 
+import androidx.test.filters.MediumTest;
+
 public class GridStackFromBottomTest extends ActivityInstrumentationTestCase<GridStackFromBottom> {
     private GridStackFromBottom mActivity;
     private GridView mGridView;
diff --git a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
index ad89bb6..34c19c3 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
@@ -16,20 +16,20 @@
 
 package android.widget.gridview;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.GridView;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 import java.util.Random;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchSetSelectionTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchSetSelectionTest.java
index ca789af..ab5fcfa 100644
--- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchSetSelectionTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchSetSelectionTest.java
@@ -17,14 +17,14 @@
 package android.widget.gridview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.View;
 import android.widget.GridView;
-
 import android.widget.gridview.GridSimple;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * Tests setting the selection in touch mode
  */
diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomManyTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomManyTest.java
index 9a8d307..e312873 100644
--- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomManyTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomManyTest.java
@@ -16,14 +16,14 @@
 
 package android.widget.gridview.touch;
 
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
+import android.view.View;
+import android.widget.GridView;
 import android.widget.gridview.GridStackFromBottomMany;
 
-import android.widget.GridView;
-import android.view.View;
-import android.test.ActivityInstrumentationTestCase;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 public class GridTouchStackFromBottomManyTest extends ActivityInstrumentationTestCase<GridStackFromBottomMany> {
     private GridStackFromBottomMany mActivity;
diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomTest.java
index d8d4e43..c98c10a 100644
--- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchStackFromBottomTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.gridview.touch;
 
-import android.widget.gridview.GridStackFromBottom;
-import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.MediumTest;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.widget.GridView;
+import android.test.TouchUtils;
 import android.view.View;
+import android.widget.GridView;
+import android.widget.gridview.GridStackFromBottom;
+
+import androidx.test.filters.MediumTest;
 
 public class GridTouchStackFromBottomTest extends ActivityInstrumentationTestCase<GridStackFromBottom> {
     private GridStackFromBottom mActivity;
diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java
index 55a66d9..0d3092c 100644
--- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingStackFromBottomTest.java
@@ -18,16 +18,16 @@
 
 import android.content.Context;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.GridView;
-
 import android.widget.gridview.GridVerticalSpacingStackFromBottom;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class GridTouchVerticalSpacingStackFromBottomTest extends ActivityInstrumentationTestCase<GridVerticalSpacingStackFromBottom> {
     private GridVerticalSpacingStackFromBottom mActivity;
     private GridView mGridView;
diff --git a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingTest.java b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingTest.java
index bae4ee7..e831e62 100644
--- a/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingTest.java
+++ b/core/tests/coretests/src/android/widget/gridview/touch/GridTouchVerticalSpacingTest.java
@@ -17,16 +17,16 @@
 package android.widget.gridview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.GridView;
-
 import android.widget.gridview.GridVerticalSpacing;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class GridTouchVerticalSpacingTest extends ActivityInstrumentationTestCase<GridVerticalSpacing> {
     private GridVerticalSpacing mActivity;
     private GridView mGridView;
diff --git a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravity.java b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravity.java
index 9791e36..d159be8 100644
--- a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravity.java
+++ b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravity.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.frame;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class FrameLayoutGravity extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravityTest.java b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravityTest.java
index fe4e932..0cab660 100644
--- a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravityTest.java
+++ b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutGravityTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.layout.frame;
 
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.ViewAsserts;
 import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.ViewAsserts;
 import android.view.View;
-import android.widget.layout.frame.FrameLayoutGravity;
+
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 public class FrameLayoutGravityTest extends ActivityInstrumentationTestCase<FrameLayoutGravity> {
diff --git a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMargin.java b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMargin.java
index 81b3ea1..8c54557 100644
--- a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMargin.java
+++ b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMargin.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.frame;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class FrameLayoutMargin extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMarginTest.java b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMarginTest.java
index c052d65..4973078 100644
--- a/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMarginTest.java
+++ b/core/tests/coretests/src/android/widget/layout/frame/FrameLayoutMarginTest.java
@@ -16,13 +16,14 @@
 
 package android.widget.layout.frame;
 
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.ViewAsserts;
 import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.ViewAsserts;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.layout.frame.FrameLayoutMargin;
+
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 public class FrameLayoutMarginTest extends ActivityInstrumentationTestCase<FrameLayoutMargin> {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravity.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravity.java
index 766dd0a..79a34e5 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravity.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravity.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class BaselineAlignmentCenterGravity extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravityTest.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravityTest.java
index 079e9d0..60b7c2f 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravityTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentCenterGravityTest.java
@@ -18,13 +18,13 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
 import android.view.View;
 import android.widget.Button;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.BaselineAlignmentCenterGravity;
 
 public class BaselineAlignmentCenterGravityTest extends ActivityInstrumentationTestCase<BaselineAlignmentCenterGravity> {
     private Button mButton1;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentSpinnerButton.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentSpinnerButton.java
index c3bfe3a..a429b75 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentSpinnerButton.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentSpinnerButton.java
@@ -18,12 +18,12 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.HorizontalOrientationVerticalAlignment;
 
 public class BaselineAlignmentSpinnerButton extends ActivityInstrumentationTestCase<HorizontalOrientationVerticalAlignment> {
     private View mSpinner;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeight.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeight.java
index 5ed5e71..f33feb0 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeight.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeight.java
@@ -16,12 +16,12 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
 
+import com.android.frameworks.coretests.R;
+
 public class BaselineAlignmentZeroWidthAndWeight extends Activity {
     @Override
     protected void onCreate(Bundle icicle) {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java
index 2dd2bb8..443b0f7 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineAlignmentZeroWidthAndWeightTest.java
@@ -16,16 +16,15 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.BaselineAlignmentZeroWidthAndWeight;
-import android.widget.layout.linear.ExceptionTextView;
-
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 public class BaselineAlignmentZeroWidthAndWeightTest extends ActivityInstrumentationTestCase<BaselineAlignmentZeroWidthAndWeight> {
     private Button mShowButton;
 
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineButtons.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineButtons.java
index c9ad831..9d91316 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineButtons.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineButtons.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class BaselineButtons extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/linear/BaselineButtonsTest.java b/core/tests/coretests/src/android/widget/layout/linear/BaselineButtonsTest.java
index 6f1fc90..ac3c5d8 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/BaselineButtonsTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/BaselineButtonsTest.java
@@ -18,12 +18,12 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 import android.widget.ImageButton;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.BaselineButtons;
 
 public class BaselineButtonsTest extends ActivityInstrumentationTestCase<BaselineButtons> {
     private View mCurrentTime;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java b/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
index 6129b5b..c684501 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/ExceptionTextView.java
@@ -21,7 +21,6 @@
 import android.util.AttributeSet;
 import android.widget.EditText;
 
-
 /**
  * A special EditText that sets {@link #isFailed()} to true as its internal makeNewLayout() method is called
  * with a width lower than 0. This is used to fail the unit test in
diff --git a/core/tests/coretests/src/android/widget/layout/linear/FillInWrap.java b/core/tests/coretests/src/android/widget/layout/linear/FillInWrap.java
index 50aa5b7..c8a5f34 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/FillInWrap.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/FillInWrap.java
@@ -16,12 +16,12 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 public class FillInWrap extends Activity {
     @Override
     protected void onCreate(Bundle icicle) {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/FillInWrapTest.java b/core/tests/coretests/src/android/widget/layout/linear/FillInWrapTest.java
index f161802..0e69efc 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/FillInWrapTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/FillInWrapTest.java
@@ -18,9 +18,10 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
 
 public class FillInWrapTest extends ActivityInstrumentationTestCase<FillInWrap> {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/HorizontalOrientationVerticalAlignment.java b/core/tests/coretests/src/android/widget/layout/linear/HorizontalOrientationVerticalAlignment.java
index 9f937a9..255f7b3 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/HorizontalOrientationVerticalAlignment.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/HorizontalOrientationVerticalAlignment.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class HorizontalOrientationVerticalAlignment extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
index 83331ca..a0745dd 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
@@ -16,14 +16,14 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 
+import com.android.frameworks.coretests.R;
+
 public class LLEditTextThenButton extends Activity {
     private EditText mEditText;
     private Button mButton;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
index ab2f060..1153062 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
@@ -18,10 +18,10 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.view.View;
 import android.widget.Button;
 import android.widget.LinearLayout;
+
 import com.android.frameworks.coretests.R;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons2.java b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons2.java
index 77f564d..0aca699 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons2.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons2.java
@@ -22,5 +22,4 @@
  */
 public class LLOfButtons2  extends LLOfButtons1 {
 
-
 }
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTexts.java b/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTexts.java
index 90db788..5d37245 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTexts.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTexts.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class LinearLayoutEditTexts extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTextsTest.java b/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTextsTest.java
index d5998b7..966ed6d 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTextsTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LinearLayoutEditTextsTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.layout.linear;
 
-import android.widget.layout.linear.LinearLayoutEditTexts;
-import com.android.frameworks.coretests.R;
-
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.view.View;
 import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase;
+import android.view.View;
+
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
 
 public class LinearLayoutEditTextsTest extends ActivityInstrumentationTestCase<LinearLayoutEditTexts> {
     private View mChild;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/Weight.java b/core/tests/coretests/src/android/widget/layout/linear/Weight.java
index 20edd7c..3722a14f 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/Weight.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/Weight.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 public class Weight extends Activity {
     @Override
     protected void onCreate(Bundle icicle) {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/WeightSum.java b/core/tests/coretests/src/android/widget/layout/linear/WeightSum.java
index 2e421da..144600b 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/WeightSum.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/WeightSum.java
@@ -16,11 +16,10 @@
 
 package android.widget.layout.linear;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.View;
+
+import com.android.frameworks.coretests.R;
 
 public class WeightSum extends Activity {
     @Override
diff --git a/core/tests/coretests/src/android/widget/layout/linear/WeightSumTest.java b/core/tests/coretests/src/android/widget/layout/linear/WeightSumTest.java
index f9a94ce..1d07db2 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/WeightSumTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/WeightSumTest.java
@@ -18,11 +18,11 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.WeightSum;
 
 public class WeightSumTest extends ActivityInstrumentationTestCase<WeightSum> {
     private View mChild;
diff --git a/core/tests/coretests/src/android/widget/layout/linear/WeightTest.java b/core/tests/coretests/src/android/widget/layout/linear/WeightTest.java
index 1c42e7c..db52495 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/WeightTest.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/WeightTest.java
@@ -18,13 +18,13 @@
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 import com.android.frameworks.coretests.R;
-import android.widget.layout.linear.Weight;
 
 @Suppress // Failing.
 public class WeightTest extends ActivityInstrumentationTestCase<Weight> {
diff --git a/core/tests/coretests/src/android/widget/layout/table/AddColumn.java b/core/tests/coretests/src/android/widget/layout/table/AddColumn.java
index 400c32c..b407941 100644
--- a/core/tests/coretests/src/android/widget/layout/table/AddColumn.java
+++ b/core/tests/coretests/src/android/widget/layout/table/AddColumn.java
@@ -16,8 +16,6 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
@@ -26,6 +24,8 @@
 import android.widget.TableRow;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * This test adds an extra row with an extra column in the table.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/AddColumnTest.java b/core/tests/coretests/src/android/widget/layout/table/AddColumnTest.java
index bfb4d17..08ae030 100644
--- a/core/tests/coretests/src/android/widget/layout/table/AddColumnTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/AddColumnTest.java
@@ -16,16 +16,16 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.AddColumn;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.TableLayout;
 import android.widget.TableRow;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.AddColumn} is
  * setup to exercise the case of adding row programmatically in a table.
diff --git a/core/tests/coretests/src/android/widget/layout/table/CellSpan.java b/core/tests/coretests/src/android/widget/layout/table/CellSpan.java
index d91cf56..3102ac1 100644
--- a/core/tests/coretests/src/android/widget/layout/table/CellSpan.java
+++ b/core/tests/coretests/src/android/widget/layout/table/CellSpan.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercise table layout with cells spanning.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/CellSpanTest.java b/core/tests/coretests/src/android/widget/layout/table/CellSpanTest.java
index 331ec45..aa8e66c 100644
--- a/core/tests/coretests/src/android/widget/layout/table/CellSpanTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/CellSpanTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.CellSpan;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.CellSpan} is
  * setup to exercise tables in which cells use spanning.
diff --git a/core/tests/coretests/src/android/widget/layout/table/FixedWidth.java b/core/tests/coretests/src/android/widget/layout/table/FixedWidth.java
index 435815a..c587f74 100644
--- a/core/tests/coretests/src/android/widget/layout/table/FixedWidth.java
+++ b/core/tests/coretests/src/android/widget/layout/table/FixedWidth.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercise table layout with cells having a fixed width and height.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/FixedWidthTest.java b/core/tests/coretests/src/android/widget/layout/table/FixedWidthTest.java
index b20ec84..7d02453 100644
--- a/core/tests/coretests/src/android/widget/layout/table/FixedWidthTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/FixedWidthTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.FixedWidth;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.FixedWidth} is
  * setup to exercise tables in which cells use fixed width and height.
diff --git a/core/tests/coretests/src/android/widget/layout/table/HorizontalGravity.java b/core/tests/coretests/src/android/widget/layout/table/HorizontalGravity.java
index 1444f60f..6f5148b 100644
--- a/core/tests/coretests/src/android/widget/layout/table/HorizontalGravity.java
+++ b/core/tests/coretests/src/android/widget/layout/table/HorizontalGravity.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercise table layout with cells using a horizontal gravity.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/HorizontalGravityTest.java b/core/tests/coretests/src/android/widget/layout/table/HorizontalGravityTest.java
index 964df82..73e8334 100644
--- a/core/tests/coretests/src/android/widget/layout/table/HorizontalGravityTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/HorizontalGravityTest.java
@@ -16,14 +16,14 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.HorizontalGravity;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.HorizontalGravity} is
  * setup to exercise tables in which cells use horizontal gravity.
diff --git a/core/tests/coretests/src/android/widget/layout/table/VerticalGravity.java b/core/tests/coretests/src/android/widget/layout/table/VerticalGravity.java
index 4fdb378..9055b32 100644
--- a/core/tests/coretests/src/android/widget/layout/table/VerticalGravity.java
+++ b/core/tests/coretests/src/android/widget/layout/table/VerticalGravity.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercise table layout with cells using a vertical gravity.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/VerticalGravityTest.java b/core/tests/coretests/src/android/widget/layout/table/VerticalGravityTest.java
index 1d6be3f..f14fa1c 100644
--- a/core/tests/coretests/src/android/widget/layout/table/VerticalGravityTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/VerticalGravityTest.java
@@ -16,15 +16,15 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.VerticalGravity;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.test.ViewAsserts;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.VerticalGravity} is
  * setup to exercise tables in which cells use vertical gravity.
diff --git a/core/tests/coretests/src/android/widget/layout/table/Weight.java b/core/tests/coretests/src/android/widget/layout/table/Weight.java
index 6d4d51d..5c08247 100644
--- a/core/tests/coretests/src/android/widget/layout/table/Weight.java
+++ b/core/tests/coretests/src/android/widget/layout/table/Weight.java
@@ -16,11 +16,11 @@
 
 package android.widget.layout.table;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercise table layout with cells having a weight.
  */
diff --git a/core/tests/coretests/src/android/widget/layout/table/WeightTest.java b/core/tests/coretests/src/android/widget/layout/table/WeightTest.java
index b665573..fcf3de2 100644
--- a/core/tests/coretests/src/android/widget/layout/table/WeightTest.java
+++ b/core/tests/coretests/src/android/widget/layout/table/WeightTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.layout.table;
 
-import android.widget.layout.table.Weight;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.View;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * {@link android.widget.layout.table.Weight} is
  * setup to exercise tables in which cells use a weight.
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
index a386ebd..cd76d70 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravity.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import android.view.Gravity;
-
 import android.util.ListScenario;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
index 519816c..e048e3e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravityMany.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import android.view.Gravity;
-
 import android.util.ListScenario;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravityManyTest.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravityManyTest.java
index e1171eb..bd8dbe4 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravityManyTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravityManyTest.java
@@ -17,10 +17,9 @@
 package android.widget.listview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.ListView;
 
-import android.widget.listview.ListBottomGravityMany;
+import androidx.test.filters.MediumTest;
 
 public class ListBottomGravityManyTest extends ActivityInstrumentationTestCase<ListBottomGravityMany> {
     private ListBottomGravityMany mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListBottomGravityTest.java b/core/tests/coretests/src/android/widget/listview/ListBottomGravityTest.java
index c595f62..8da7358 100644
--- a/core/tests/coretests/src/android/widget/listview/ListBottomGravityTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListBottomGravityTest.java
@@ -17,10 +17,9 @@
 package android.widget.listview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.ListView;
 
-import android.widget.listview.ListBottomGravity;
+import androidx.test.filters.MediumTest;
 
 public class ListBottomGravityTest extends ActivityInstrumentationTestCase<ListBottomGravity> {
     private ListBottomGravity mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java b/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
index bbed73c..8640741 100644
--- a/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
+++ b/core/tests/coretests/src/android/widget/listview/ListButtonsDiagonalAcrossItems.java
@@ -16,10 +16,10 @@
 
 package android.widget.listview;
 
-import android.util.ListItemFactory;
 import static android.util.ListItemFactory.Slot;
-import android.util.ListScenario;
 
+import android.util.ListItemFactory;
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListEmptyViewTest.java b/core/tests/coretests/src/android/widget/listview/ListEmptyViewTest.java
index 258d3ef..81d71a9 100644
--- a/core/tests/coretests/src/android/widget/listview/ListEmptyViewTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListEmptyViewTest.java
@@ -19,12 +19,13 @@
 import android.app.Instrumentation;
 import android.content.Intent;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class ListEmptyViewTest extends ActivityInstrumentationTestCase<ListWithEmptyView> {
     private ListWithEmptyView mActivity;
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListFilter.java b/core/tests/coretests/src/android/widget/listview/ListFilter.java
index c2ac90e..1cda717 100644
--- a/core/tests/coretests/src/android/widget/listview/ListFilter.java
+++ b/core/tests/coretests/src/android/widget/listview/ListFilter.java
@@ -25,7 +25,6 @@
 
 import com.android.frameworks.coretests.R;
 
-
 /**
  * Tests hiding and showing the list filter by hiding and showing an ancestor of the 
  * ListView
diff --git a/core/tests/coretests/src/android/widget/listview/ListFocusableTest.java b/core/tests/coretests/src/android/widget/listview/ListFocusableTest.java
index bf18a13..10b4a79 100644
--- a/core/tests/coretests/src/android/widget/listview/ListFocusableTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListFocusableTest.java
@@ -17,10 +17,11 @@
 package android.widget.listview;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListView;
-import android.widget.ListAdapter;
 import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import androidx.test.filters.MediumTest;
 
 public class ListFocusableTest extends ActivityInstrumentationTestCase<ListTopGravity> {
     private ListTopGravity mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java
index 33d61a0..c691ed7 100644
--- a/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java
@@ -17,10 +17,11 @@
 package android.widget.listview;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.ListView;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+
 import java.util.Arrays;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java b/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
index 1f59c30..74eda3b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
+++ b/core/tests/coretests/src/android/widget/listview/ListHeterogeneous.java
@@ -16,11 +16,10 @@
 
 package android.widget.listview;
 
-import android.view.View;
-import android.view.ViewGroup;
-
 import android.util.ListItemFactory;
 import android.util.ListScenario;
+import android.view.View;
+import android.view.ViewGroup;
 
 /**
  * List that has different view types
diff --git a/core/tests/coretests/src/android/widget/listview/ListHeterogeneousTest.java b/core/tests/coretests/src/android/widget/listview/ListHeterogeneousTest.java
index 01b39db..dbd58d7 100644
--- a/core/tests/coretests/src/android/widget/listview/ListHeterogeneousTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListHeterogeneousTest.java
@@ -18,12 +18,11 @@
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.ListView;
 
-import android.widget.listview.ListHeterogeneous;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 public class ListHeterogeneousTest extends ActivityInstrumentationTestCase<ListHeterogeneous> {
     private ListHeterogeneous mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java b/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
index 2ff65de..e98de9c 100644
--- a/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
+++ b/core/tests/coretests/src/android/widget/listview/ListHorizontalFocusWithinItemWins.java
@@ -16,11 +16,11 @@
 
 package android.widget.listview;
 
-import android.util.ListItemFactory;
 import static android.util.ListItemFactory.Slot;
-import android.util.ListScenario;
 
 import android.content.Context;
+import android.util.ListItemFactory;
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
diff --git a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
index a373a5b..6622c0d 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
@@ -18,10 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.os.Handler;
 import android.widget.ArrayAdapter;
-import android.widget.GridView;
-import android.widget.TextView;
 import android.widget.ListView;
 
 import com.android.frameworks.coretests.R;
diff --git a/core/tests/coretests/src/android/widget/listview/ListInHorizontalTest.java b/core/tests/coretests/src/android/widget/listview/ListInHorizontalTest.java
index 3643f79..d8508ec 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInHorizontalTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInHorizontalTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import android.widget.listview.ListInHorizontal;
-
 public class ListInHorizontalTest extends ListUnspecifiedMeasure<ListInHorizontal> {
     public ListInHorizontalTest() {
         super(ListInHorizontal.class);
diff --git a/core/tests/coretests/src/android/widget/listview/ListInVertical.java b/core/tests/coretests/src/android/widget/listview/ListInVertical.java
index 3b4885a..4ecf25d 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInVertical.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInVertical.java
@@ -18,10 +18,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.os.Handler;
 import android.widget.ArrayAdapter;
-import android.widget.GridView;
-import android.widget.TextView;
 import android.widget.ListView;
 
 import com.android.frameworks.coretests.R;
diff --git a/core/tests/coretests/src/android/widget/listview/ListInVerticalTest.java b/core/tests/coretests/src/android/widget/listview/ListInVerticalTest.java
index 8586429..5e385a3 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInVerticalTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInVerticalTest.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import android.widget.listview.ListInVertical;
-
 public class ListInVerticalTest extends ListUnspecifiedMeasure<ListInVertical> {
     public ListInVerticalTest() {
         super(ListInVertical.class);
diff --git a/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java b/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
index d5da28e..0ec7a24 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInterleaveFocusables.java
@@ -16,13 +16,14 @@
 
 package android.widget.listview;
 
+import android.util.ListItemFactory;
+import android.util.ListScenario;
 import android.view.View;
- import android.view.ViewGroup;
- import com.google.android.collect.Sets;
- import android.util.ListScenario;
- import android.util.ListItemFactory;
+import android.view.ViewGroup;
 
- import java.util.Set;
+import com.google.android.collect.Sets;
+
+import java.util.Set;
 
 /**
  * List that interleaves focusable items.
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
index f7c01b1..3159e53 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusableAboveUnfocusable.java
@@ -16,12 +16,10 @@
 
 package android.widget.listview;
 
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
 import android.util.ListItemFactory;
 import android.util.ListScenario;
+import android.view.View;
+import android.view.ViewGroup;
 
 /**
  * A list where the items may befocusable, but the second item isn't actually focusabe.
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
index b529b2e..861e2a91 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesClose.java
@@ -16,8 +16,8 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
 import android.util.ListItemFactory;
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
index 59987ec..e9c9c1d 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemFocusablesFarApart.java
@@ -16,10 +16,10 @@
 
 package android.widget.listview;
 
-import android.view.View;
-import android.view.ViewGroup;
 import android.util.ListItemFactory;
 import android.util.ListScenario;
+import android.view.View;
+import android.view.ViewGroup;
 
 /**
  * A list where each item is tall with buttons that are farther apart than the screen
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java b/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
index ea2c5f2..2a0e013 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemISVAndButton.java
@@ -17,13 +17,13 @@
 package android.widget.listview;
 
 import android.content.Context;
+import android.util.InternalSelectionView;
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-import android.util.InternalSelectionView;
-import android.util.ListScenario;
 
 /**
  * Each item is an internal selection view, a button, and some filler
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemRequestRectAboveThinFirstItemTest.java b/core/tests/coretests/src/android/widget/listview/ListItemRequestRectAboveThinFirstItemTest.java
index 73eb0a8..91ff06b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemRequestRectAboveThinFirstItemTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemRequestRectAboveThinFirstItemTest.java
@@ -18,13 +18,13 @@
 
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.view.View;
 import android.view.KeyEvent;
+import android.view.View;
 import android.widget.ListView;
-import android.widget.listview.ListOfThinItems;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 public class ListItemRequestRectAboveThinFirstItemTest
         extends ActivityInstrumentationTestCase<ListOfThinItems> {
diff --git a/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java b/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
index a5fe17a..d80fd90 100644
--- a/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
+++ b/core/tests/coretests/src/android/widget/listview/ListItemsExpandOnSelection.java
@@ -17,13 +17,12 @@
 package android.widget.listview;
 
 import android.content.Context;
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
 import android.widget.TextView;
 
-import android.util.ListScenario;
-
 /**
  * A list where each item expands by 1.5 when selected.
  */
diff --git a/core/tests/coretests/src/android/widget/listview/ListManagedCursor.java b/core/tests/coretests/src/android/widget/listview/ListManagedCursor.java
index 12b5ef4..54f302c 100644
--- a/core/tests/coretests/src/android/widget/listview/ListManagedCursor.java
+++ b/core/tests/coretests/src/android/widget/listview/ListManagedCursor.java
@@ -20,14 +20,13 @@
 import android.content.Intent;
 import android.database.Cursor;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.provider.Contacts.People;
+import android.provider.Settings;
 import android.view.View;
 import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ListAdapter;
 import android.widget.SimpleCursorAdapter;
-import android.widget.AdapterView.OnItemClickListener;
-
 
 public class ListManagedCursor extends ListActivity implements OnItemClickListener {
     
diff --git a/core/tests/coretests/src/android/widget/listview/ListManagedCursorTest.java b/core/tests/coretests/src/android/widget/listview/ListManagedCursorTest.java
index bc3776c..8e0b6fe 100644
--- a/core/tests/coretests/src/android/widget/listview/ListManagedCursorTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListManagedCursorTest.java
@@ -18,11 +18,12 @@
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
 import android.view.KeyEvent;
 import android.widget.ListView;
-import android.test.TouchUtils;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 /**
  * Tests restoring the scroll position in a list with a managed cursor.
diff --git a/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java b/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
index 919ef69..70b9081 100644
--- a/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
+++ b/core/tests/coretests/src/android/widget/listview/ListOfTouchables.java
@@ -16,12 +16,11 @@
 
 package android.widget.listview;
 
+import android.util.ListScenario;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 
-import android.util.ListScenario;
-
 /**
  * Each list item has two focusables that are close enough together that
  * it shouldn't require panning to move focus.
diff --git a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
index 76814fb..075712e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
+++ b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
@@ -18,11 +18,11 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.widget.ImageButton;
-import android.view.ViewDebug;
 import android.view.View;
+import android.view.ViewDebug;
+import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
+import android.widget.ListView;
 
 import com.android.frameworks.coretests.R;
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListRetainsFocusAcrossLayoutsTest.java b/core/tests/coretests/src/android/widget/listview/ListRetainsFocusAcrossLayoutsTest.java
index 896bd19..be14de8 100644
--- a/core/tests/coretests/src/android/widget/listview/ListRetainsFocusAcrossLayoutsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListRetainsFocusAcrossLayoutsTest.java
@@ -16,12 +16,11 @@
 
 package android.widget.listview;
 
-import android.widget.listview.ListItemFocusablesClose;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 
+import androidx.test.filters.MediumTest;
+
 public class ListRetainsFocusAcrossLayoutsTest extends ActivityInstrumentationTestCase<ListItemFocusablesClose> {
 
     public ListRetainsFocusAcrossLayoutsTest() {
diff --git a/core/tests/coretests/src/android/widget/listview/ListScrollListenerTest.java b/core/tests/coretests/src/android/widget/listview/ListScrollListenerTest.java
index 7b29a66..28addd6 100644
--- a/core/tests/coretests/src/android/widget/listview/ListScrollListenerTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListScrollListenerTest.java
@@ -19,12 +19,13 @@
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.AbsListView;
 import android.widget.ListView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class ListScrollListenerTest extends ActivityInstrumentationTestCase<ListScrollListener> implements
         AbsListView.OnScrollListener {
     private ListScrollListener mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListSetSelection.java b/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
index 6c2e264..af8e899 100644
--- a/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
+++ b/core/tests/coretests/src/android/widget/listview/ListSetSelection.java
@@ -16,12 +16,12 @@
 
 package android.widget.listview;
 
+import android.os.Bundle;
 import android.util.ListScenario;
 import android.view.KeyEvent;
 import android.view.View;
-import android.os.Bundle;
-import android.widget.LinearLayout;
 import android.widget.Button;
+import android.widget.LinearLayout;
 
 /**
  * List of 1,000 items used to test calls to setSelection() in touch mode.
diff --git a/core/tests/coretests/src/android/widget/listview/ListSetSelectionTest.java b/core/tests/coretests/src/android/widget/listview/ListSetSelectionTest.java
index 4cef164..2caca13 100644
--- a/core/tests/coretests/src/android/widget/listview/ListSetSelectionTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListSetSelectionTest.java
@@ -17,10 +17,11 @@
 package android.widget.listview;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.ListView;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * Basic tests of setting & clearing the selection
  */
diff --git a/core/tests/coretests/src/android/widget/listview/ListSimple.java b/core/tests/coretests/src/android/widget/listview/ListSimple.java
index 6accae1..f53638e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListSimple.java
+++ b/core/tests/coretests/src/android/widget/listview/ListSimple.java
@@ -16,11 +16,10 @@
 
 package android.widget.listview;
 
+import android.os.Bundle;
 import android.util.ListScenario;
-
 import android.view.View;
 import android.view.ViewGroup;
-import android.os.Bundle;
 import android.widget.TextView;
 
 public class ListSimple extends ListScenario {
diff --git a/core/tests/coretests/src/android/widget/listview/ListTakeFocusFromSide.java b/core/tests/coretests/src/android/widget/listview/ListTakeFocusFromSide.java
index 95f09f6..c4e9fe9 100644
--- a/core/tests/coretests/src/android/widget/listview/ListTakeFocusFromSide.java
+++ b/core/tests/coretests/src/android/widget/listview/ListTakeFocusFromSide.java
@@ -16,17 +16,17 @@
 
 package android.widget.listview;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.os.Bundle;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * Exercises moving focus into the list from the side
  */
diff --git a/core/tests/coretests/src/android/widget/listview/ListThrasher.java b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
index 0237a95..d82f68d 100644
--- a/core/tests/coretests/src/android/widget/listview/ListThrasher.java
+++ b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
@@ -16,19 +16,19 @@
 
 package android.widget.listview;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.LayoutInflater;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 import java.util.Random;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListTopGravity.java b/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
index 986cc57..31339e9 100644
--- a/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
+++ b/core/tests/coretests/src/android/widget/listview/ListTopGravity.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import android.view.Gravity;
-
 import android.util.ListScenario;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/listview/ListUnspecifiedMeasure.java b/core/tests/coretests/src/android/widget/listview/ListUnspecifiedMeasure.java
index 199d069..0fc87ea 100644
--- a/core/tests/coretests/src/android/widget/listview/ListUnspecifiedMeasure.java
+++ b/core/tests/coretests/src/android/widget/listview/ListUnspecifiedMeasure.java
@@ -16,13 +16,14 @@
 
 package android.widget.listview;
 
-import com.android.frameworks.coretests.R;
-
-import android.test.ActivityInstrumentationTestCase;
 import android.app.Activity;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.test.ActivityInstrumentationTestCase;
 import android.widget.ListView;
 
+import androidx.test.filters.MediumTest;
+
+import com.android.frameworks.coretests.R;
+
 public class ListUnspecifiedMeasure<T extends Activity> extends ActivityInstrumentationTestCase<T> {
     private T mActivity;
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListViewHeightTest.java b/core/tests/coretests/src/android/widget/listview/ListViewHeightTest.java
index 5ab2757..63941f1 100644
--- a/core/tests/coretests/src/android/widget/listview/ListViewHeightTest.java
+++ b/core/tests/coretests/src/android/widget/listview/ListViewHeightTest.java
@@ -18,12 +18,12 @@
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.Button;
 import android.widget.ListView;
 
+import androidx.test.filters.MediumTest;
+
 import com.android.frameworks.coretests.R;
-import android.widget.listview.ListViewHeight;
 
 public class ListViewHeightTest extends ActivityInstrumentationTestCase<ListViewHeight> {
     private ListViewHeight mActivity;
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithDisappearingItemBug.java b/core/tests/coretests/src/android/widget/listview/ListWithDisappearingItemBug.java
index 348ea1b..10ba8b7 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithDisappearingItemBug.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithDisappearingItemBug.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.database.Cursor;
 import android.os.Bundle;
@@ -32,6 +30,8 @@
 import android.widget.SimpleCursorAdapter;
 import android.widget.Toast;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * See 1080989. You need some contacts for this adapter.
  */
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithEmptyView.java b/core/tests/coretests/src/android/widget/listview/ListWithEmptyView.java
index 74dd06c..52273fd 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithEmptyView.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithEmptyView.java
@@ -16,8 +16,6 @@
 
 package android.widget.listview;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.ListActivity;
 import android.content.Context;
 import android.os.Bundle;
@@ -26,6 +24,8 @@
 import android.view.View;
 import android.widget.ArrayAdapter;
 
+import com.android.frameworks.coretests.R;
+
 
 /**
  * Tests using an empty view with a list */
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java b/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
index aea091a..6030582 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithHeaders.java
@@ -16,9 +16,8 @@
 
 package android.widget.listview;
 
-import android.util.ListScenario;
-
 import android.os.Bundle;
+import android.util.ListScenario;
 import android.widget.Button;
 import android.widget.ListAdapter;
 import android.widget.ListView;
diff --git a/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java b/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
index 26e1d5d..13e770c 100644
--- a/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
+++ b/core/tests/coretests/src/android/widget/listview/ListWithOnItemSelectedAction.java
@@ -16,8 +16,8 @@
 
 package android.widget.listview;
 
-import android.widget.TextView;
 import android.util.ListScenario;
+import android.widget.TextView;
 
 /**
  * The header text view echos the value of the selected item by using (indirectly)
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListInterleaveFocusablesTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListInterleaveFocusablesTest.java
index ec8ab7e..22c28c2 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListInterleaveFocusablesTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListInterleaveFocusablesTest.java
@@ -17,13 +17,14 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.util.ListUtil;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.listview.ListInterleaveFocusables;
 
+import androidx.test.filters.MediumTest;
+
 public class ListInterleaveFocusablesTest extends ActivityInstrumentationTestCase2<ListInterleaveFocusables> {
     private ListView mListView;
     private ListUtil mListUtil;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java
index 82f48801..c645b7c 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusableAboveUnfocusableTest.java
@@ -17,11 +17,12 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListView;
 import android.view.KeyEvent;
+import android.widget.ListView;
 import android.widget.listview.ListItemFocusableAboveUnfocusable;
 
+import androidx.test.filters.MediumTest;
+
 public class ListItemFocusableAboveUnfocusableTest extends ActivityInstrumentationTestCase<ListItemFocusableAboveUnfocusable> {
     private ListView mListView;
 
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesCloseTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesCloseTest.java
index 3b30ebe..c7525b3 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesCloseTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesCloseTest.java
@@ -17,12 +17,13 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.listview.ListItemFocusablesClose;
 
+import androidx.test.filters.MediumTest;
+
 public class ListItemFocusablesCloseTest extends ActivityInstrumentationTestCase<ListItemFocusablesClose> {
     private ListView mListView;
     private int mListTop;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesFarApartTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesFarApartTest.java
index 475930d..4bb2206 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesFarApartTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemFocusablesFarApartTest.java
@@ -17,7 +17,6 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -25,6 +24,8 @@
 import android.widget.ListView;
 import android.widget.listview.ListItemFocusablesFarApart;
 
+import androidx.test.filters.MediumTest;
+
 public class ListItemFocusablesFarApartTest extends ActivityInstrumentationTestCase<ListItemFocusablesFarApart> {
     private ListView mListView;
     private int mListTop;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemsExpandOnSelectionTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemsExpandOnSelectionTest.java
index 91a1eba..7605291 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemsExpandOnSelectionTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListItemsExpandOnSelectionTest.java
@@ -17,13 +17,14 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.ListView;
 import android.view.KeyEvent;
+import android.widget.ListView;
 import android.widget.listview.ListItemsExpandOnSelection;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListItemsExpandOnSelectionTest extends ActivityInstrumentationTestCase<ListItemsExpandOnSelection> {
     private ListView mListView;
     private int mListTop;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java
index 5bc121a..fdae483 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListLastItemPartiallyVisibleTest.java
@@ -17,12 +17,13 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListView;
-import android.view.View;
 import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ListView;
 import android.widget.listview.ListLastItemPartiallyVisible;
 
+import androidx.test.filters.MediumTest;
+
 public class ListLastItemPartiallyVisibleTest extends ActivityInstrumentationTestCase<ListLastItemPartiallyVisible> {
     private ListView mListView;
     private int mListBottom;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java
index bda71d0..d44b130 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsShorterThanScreenTest.java
@@ -17,14 +17,15 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.listview.ListOfItemsShorterThanScreen;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListOfItemsShorterThanScreenTest
         extends ActivityInstrumentationTestCase<ListOfItemsShorterThanScreen> {
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java
index 2135445..1decdad 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfItemsTallerThanScreenTest.java
@@ -17,13 +17,14 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.listview.ListOfItemsTallerThanScreen;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListOfItemsTallerThanScreenTest
         extends ActivityInstrumentationTestCase2<ListOfItemsTallerThanScreen> {
 
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortShortTallShortShortTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortShortTallShortShortTest.java
index ef70b5a..67808f1 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortShortTallShortShortTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortShortTallShortShortTest.java
@@ -17,13 +17,14 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.ListUtil;
 import android.view.KeyEvent;
 import android.widget.ListView;
 import android.widget.listview.ListOfShortShortTallShortShort;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListOfShortShortTallShortShortTest extends ActivityInstrumentationTestCase2<ListOfShortShortTallShortShort> {
     private ListView mListView;
     private ListUtil mListUtil;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortTallShortTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortTallShortTest.java
index c958591..f9aa6dc 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortTallShortTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfShortTallShortTest.java
@@ -17,11 +17,12 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListView;
 import android.view.KeyEvent;
+import android.widget.ListView;
 import android.widget.listview.ListOfShortTallShort;
 
+import androidx.test.filters.MediumTest;
+
 public class ListOfShortTallShortTest extends ActivityInstrumentationTestCase<ListOfShortTallShort> {
     private ListView mListView;
 
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfThinItemsTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfThinItemsTest.java
index c191d71..6bd1cb5 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfThinItemsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListOfThinItemsTest.java
@@ -17,14 +17,15 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.listview.ListOfThinItems;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListOfThinItemsTest extends ActivityInstrumentationTestCase<ListOfThinItems> {
     private ListView mListView;
 
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java
index 9a8e634..60bc115 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithFirstScreenUnSelectableTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.listview.arrowscroll;
 
-import android.support.test.filters.LargeTest;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.KeyEvent;
+import android.widget.AdapterView;
 import android.widget.ListView;
 import android.widget.listview.ListWithFirstScreenUnSelectable;
-import android.widget.AdapterView;
+
+import androidx.test.filters.LargeTest;
 
 @LargeTest
 public class ListWithFirstScreenUnSelectableTest
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithNoFadingEdgeTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithNoFadingEdgeTest.java
index 56ca009..a60054e2 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithNoFadingEdgeTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithNoFadingEdgeTest.java
@@ -17,12 +17,13 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.ListView;
 import android.widget.listview.ListWithNoFadingEdge;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 public class ListWithNoFadingEdgeTest extends ActivityInstrumentationTestCase<ListWithNoFadingEdge> {
 
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java
index cf319d1..80e70c6 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOffScreenNextSelectableTest.java
@@ -17,14 +17,15 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.listview.ListWithOffScreenNextSelectable;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 @Suppress // Failing.
 public class ListWithOffScreenNextSelectableTest
         extends ActivityInstrumentationTestCase<ListWithOffScreenNextSelectable> {
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOnItemSelectedActionTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOnItemSelectedActionTest.java
index feea9b2..819b739 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOnItemSelectedActionTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithOnItemSelectedActionTest.java
@@ -17,12 +17,13 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.view.KeyEvent;
 import android.widget.ListView;
 import android.widget.TextView;
-import android.view.KeyEvent;
 import android.widget.listview.ListWithOnItemSelectedAction;
 
+import androidx.test.filters.MediumTest;
+
 public class ListWithOnItemSelectedActionTest extends ActivityInstrumentationTestCase<ListWithOnItemSelectedAction> {
     private ListView mListView;
 
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java
index 211c8c8..9bbdc2a 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithScreenOfNoSelectablesTest.java
@@ -17,13 +17,14 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.listview.ListWithScreenOfNoSelectables;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListWithScreenOfNoSelectablesTest extends ActivityInstrumentationTestCase2<ListWithScreenOfNoSelectables> {
 
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithSeparatorsTest.java b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithSeparatorsTest.java
index 42058f03..21fa51d 100644
--- a/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithSeparatorsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/arrowscroll/ListWithSeparatorsTest.java
@@ -17,11 +17,12 @@
 package android.widget.listview.arrowscroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.widget.ListView;
 import android.view.KeyEvent;
+import android.widget.ListView;
 import android.widget.listview.ListWithSeparators;
 
+import androidx.test.filters.MediumTest;
+
 public class ListWithSeparatorsTest extends ActivityInstrumentationTestCase<ListWithSeparators> {
     private ListWithSeparators mActivity;
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java b/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
index 6a7466b..e9baabf 100644
--- a/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
+++ b/core/tests/coretests/src/android/widget/listview/focus/AdjacentListsWithAdjacentISVsInsideTest.java
@@ -16,14 +16,14 @@
 
 package android.widget.listview.focus;
 
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.listview.AdjacentListsWithAdjacentISVsInside;
-import android.util.InternalSelectionView;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.util.InternalSelectionView;
 import android.view.KeyEvent;
 import android.widget.ListView;
+import android.widget.listview.AdjacentListsWithAdjacentISVsInside;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 public class AdjacentListsWithAdjacentISVsInsideTest extends ActivityInstrumentationTestCase<AdjacentListsWithAdjacentISVsInside> {
 
diff --git a/core/tests/coretests/src/android/widget/listview/focus/ListButtonsDiagonalAcrossItemsTest.java b/core/tests/coretests/src/android/widget/listview/focus/ListButtonsDiagonalAcrossItemsTest.java
index 5540d65..3fbdacc 100644
--- a/core/tests/coretests/src/android/widget/listview/focus/ListButtonsDiagonalAcrossItemsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/focus/ListButtonsDiagonalAcrossItemsTest.java
@@ -16,15 +16,15 @@
 
 package android.widget.listview.focus;
 
-import android.widget.listview.ListButtonsDiagonalAcrossItems;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.FocusFinder;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 import android.widget.ListView;
+import android.widget.listview.ListButtonsDiagonalAcrossItems;
+
+import androidx.test.filters.MediumTest;
 
 /**
  * Test that ListView will override default behavior of focus searching to
diff --git a/core/tests/coretests/src/android/widget/listview/focus/ListHorizontalFocusWithinItemWinsTest.java b/core/tests/coretests/src/android/widget/listview/focus/ListHorizontalFocusWithinItemWinsTest.java
index edc60b5..5448952 100644
--- a/core/tests/coretests/src/android/widget/listview/focus/ListHorizontalFocusWithinItemWinsTest.java
+++ b/core/tests/coretests/src/android/widget/listview/focus/ListHorizontalFocusWithinItemWinsTest.java
@@ -17,12 +17,13 @@
 package android.widget.listview.focus;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.ListView;
 import android.widget.listview.ListHorizontalFocusWithinItemWins;
 
+import androidx.test.filters.MediumTest;
+
 public class ListHorizontalFocusWithinItemWinsTest extends ActivityInstrumentationTestCase<ListHorizontalFocusWithinItemWins> {
 
     private ListView mListView;
diff --git a/core/tests/coretests/src/android/widget/listview/focus/ListWithEditTextHeaderTest.java b/core/tests/coretests/src/android/widget/listview/focus/ListWithEditTextHeaderTest.java
index b449b61..0b17aaf 100644
--- a/core/tests/coretests/src/android/widget/listview/focus/ListWithEditTextHeaderTest.java
+++ b/core/tests/coretests/src/android/widget/listview/focus/ListWithEditTextHeaderTest.java
@@ -17,17 +17,18 @@
 package android.widget.listview.focus;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.FlakyTest;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.AbsListView;
 import android.widget.ListView;
 import android.widget.listview.ListWithEditTextHeader;
 
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 public class ListWithEditTextHeaderTest extends ActivityInstrumentationTestCase2<ListWithEditTextHeader> {
     private ListView mListView;
 
@@ -49,7 +50,7 @@
         assertTrue("header does not have focus", mListView.getChildAt(0).isFocused());
     }
 
-    @FlakyTest(tolerance=2)
+    @FlakyTest
     @LargeTest
     public void testClickingHeaderKeepsFocus() {
         TouchUtils.clickView(this, mListView.getChildAt(0));
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListGetSelectedViewTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListGetSelectedViewTest.java
index 28f899e..262d0f4 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListGetSelectedViewTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListGetSelectedViewTest.java
@@ -17,14 +17,14 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
-import android.widget.ListView;
 import android.view.View;
-
+import android.widget.ListView;
 import android.widget.listview.ListGetSelectedView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * This test is made to check that getSelectedView() will return
  * null in touch mode.
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListOfTouchablesTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListOfTouchablesTest.java
index ffa9a5e..48e8c5e 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListOfTouchablesTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListOfTouchablesTest.java
@@ -17,15 +17,14 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.test.TouchUtils;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.ListView;
-
 import android.widget.listview.ListOfTouchables;
-import android.test.TouchUtils;
+
+import androidx.test.filters.MediumTest;
 
 /**
  * Touch tests for a list where all of the items fit on the screen.
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListSetSelectionTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListSetSelectionTest.java
index aed513a..716683a 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListSetSelectionTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListSetSelectionTest.java
@@ -17,15 +17,15 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.View;
 import android.widget.ListView;
-
 import android.widget.listview.ListSimple;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 /**
  * Tests setting the selection in touch mode
  */
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityManyTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityManyTest.java
index 7daf64e..6a1f076 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityManyTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityManyTest.java
@@ -17,16 +17,16 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.ListView;
-
 import android.widget.listview.ListBottomGravityMany;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * Touch tests for a list where all of the items do not fit on the screen, and the list 
  * stacks from the bottom.
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityTest.java
index 4086cf0..89498d66 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListTouchBottomGravityTest.java
@@ -17,13 +17,13 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.View;
 import android.widget.ListView;
-
 import android.widget.listview.ListBottomGravity;
 
+import androidx.test.filters.MediumTest;
+
 /**
  * Touch tests for a list where all of the items fit on the screen, and the list 
  * stacks from the bottom.
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListTouchManyTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListTouchManyTest.java
index 30d56ca..c7f2371 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListTouchManyTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListTouchManyTest.java
@@ -17,16 +17,16 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.widget.ListView;
-
 import android.widget.listview.ListTopGravityMany;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * Touch tests for a list where all of the items do not fit on the screen.
  */
diff --git a/core/tests/coretests/src/android/widget/listview/touch/ListTouchTest.java b/core/tests/coretests/src/android/widget/listview/touch/ListTouchTest.java
index 5b064b3..8a557ab 100644
--- a/core/tests/coretests/src/android/widget/listview/touch/ListTouchTest.java
+++ b/core/tests/coretests/src/android/widget/listview/touch/ListTouchTest.java
@@ -17,13 +17,13 @@
 package android.widget.listview.touch;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.TouchUtils;
 import android.view.View;
 import android.widget.ListView;
-
 import android.widget.listview.ListTopGravity;
 
+import androidx.test.filters.MediumTest;
+
 /**
  * Touch tests for a list where all of the items fit on the screen.
  */
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
index a7f5c05..a30985b 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionView.java
@@ -18,7 +18,6 @@
 
 import android.util.InternalSelectionView;
 import android.util.ScrollViewScenario;
-
 import android.widget.Button;
 
 /**
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
index 8123228..825aa1a 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonAboveTallInternalSelectionViewTest.java
@@ -16,14 +16,13 @@
 
 package android.widget.scroll;
 
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.scroll.ButtonAboveTallInternalSelectionView;
-import android.util.InternalSelectionView;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.util.InternalSelectionView;
 import android.view.KeyEvent;
 
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
 @Suppress // Failing.
 public class ButtonAboveTallInternalSelectionViewTest extends
         ActivityInstrumentationTestCase<ButtonAboveTallInternalSelectionView> {
diff --git a/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java b/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
index 3d5f86d..47d36dd 100644
--- a/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
+++ b/core/tests/coretests/src/android/widget/scroll/ButtonsWithTallTextViewInBetween.java
@@ -17,7 +17,6 @@
 package android.widget.scroll;
 
 import android.util.ScrollViewScenario;
-
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.TextView;
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
index afc275f..dba07a0 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
@@ -16,15 +16,15 @@
 
 package android.widget.scroll;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
-import android.os.Bundle;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.view.View;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
+import com.android.frameworks.coretests.R;
+
 /**
  * A screen with some scenarios that exercise {@link ScrollView}'s implementation
  * of {@link android.view.ViewGroup#requestChildRectangleOnScreen}:
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleTest.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleTest.java
index f8abdb2..7c3df91 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleTest.java
@@ -16,19 +16,19 @@
 
 package android.widget.scroll;
 
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.scroll.RequestRectangleVisible;
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.test.ViewAsserts;
+import android.view.KeyEvent;
+import android.view.View;
 import android.widget.Button;
 import android.widget.ScrollView;
 import android.widget.TextView;
-import android.view.View;
-import android.view.KeyEvent;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
+
+import com.android.frameworks.coretests.R;
 
 /**
  * {@link RequestRectangleVisible} is set up to exercise the cases of moving a
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
index 731b25a..105686a 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
@@ -16,15 +16,14 @@
 
 package android.widget.scroll;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
-import android.os.Bundle;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Button;
-import android.view.View;
 import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.frameworks.coretests.R;
 
 public class RequestRectangleVisibleWithInternalScroll extends Activity {
 
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScrollTest.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScrollTest.java
index 5e9b520..1a221ff 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScrollTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScrollTest.java
@@ -16,16 +16,17 @@
 
 package android.widget.scroll;
 
-import com.android.frameworks.coretests.R;
-
 import android.test.ActivityInstrumentationTestCase;
 import android.test.ViewAsserts;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
+import androidx.test.filters.Suppress;
+
+import com.android.frameworks.coretests.R;
+
 /**
  * This is suppressed because {@link TextView#scrollBy} isn't working.
  */
diff --git a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
index 027ea0f..92a3152 100644
--- a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
+++ b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
@@ -16,15 +16,14 @@
 
 package android.widget.scroll;
 
-import com.android.frameworks.coretests.R;
-
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;
-import android.widget.Button;
 
+import com.android.frameworks.coretests.R;
 
 /**
  * Basic scroll view example
diff --git a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabelsTest.java b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabelsTest.java
index 3fd17ee..8d71f84 100644
--- a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabelsTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabelsTest.java
@@ -17,14 +17,14 @@
 package android.widget.scroll;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 public class ScrollViewButtonsAndLabelsTest
         extends ActivityInstrumentationTestCase<ScrollViewButtonsAndLabels> {
diff --git a/core/tests/coretests/src/android/widget/scroll/ShortButtons.java b/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
index 3a0f29a..90ede7d 100644
--- a/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
+++ b/core/tests/coretests/src/android/widget/scroll/ShortButtons.java
@@ -17,7 +17,6 @@
 package android.widget.scroll;
 
 import android.util.ScrollViewScenario;
-
 import android.widget.Button;
 import android.widget.LinearLayout;
 
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java
index 56d7ed2..04f5ac8 100644
--- a/core/tests/coretests/src/android/widget/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/ButtonsWithTallTextViewInBetweenTest.java
@@ -16,16 +16,16 @@
 
 package android.widget.scroll.arrowscroll;
 
-import android.widget.scroll.ButtonsWithTallTextViewInBetween;
-
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.view.View;
 import android.widget.Button;
 import android.widget.ScrollView;
 import android.widget.TextView;
+import android.widget.scroll.ButtonsWithTallTextViewInBetween;
+
+import androidx.test.filters.MediumTest;
 
 public class ButtonsWithTallTextViewInBetweenTest
         extends ActivityInstrumentationTestCase<ButtonsWithTallTextViewInBetween> {
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java
index 6ce4c15..2f45098 100644
--- a/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/MultiPageTextWithPaddingTest.java
@@ -16,14 +16,14 @@
 
 package android.widget.scroll.arrowscroll;
 
-import android.test.suitebuilder.annotation.Suppress;
-import android.widget.scroll.arrowscroll.MultiPageTextWithPadding;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
-import android.widget.TextView;
 import android.widget.ScrollView;
+import android.widget.TextView;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.filters.Suppress;
 
 @Suppress // Flaky
 public class MultiPageTextWithPaddingTest extends
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/ShortButtonsTest.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/ShortButtonsTest.java
index 267d8ee..a2928cb 100644
--- a/core/tests/coretests/src/android/widget/scroll/arrowscroll/ShortButtonsTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/ShortButtonsTest.java
@@ -16,15 +16,15 @@
 
 package android.widget.scroll.arrowscroll;
 
-import android.widget.scroll.ShortButtons;
-
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.ScrollView;
+import android.widget.scroll.ShortButtons;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 public class ShortButtonsTest extends ActivityInstrumentationTestCase<ShortButtons> {
 
diff --git a/core/tests/coretests/src/android/widget/scroll/arrowscroll/TallTextAboveButtonTest.java b/core/tests/coretests/src/android/widget/scroll/arrowscroll/TallTextAboveButtonTest.java
index 5351839..0681081 100644
--- a/core/tests/coretests/src/android/widget/scroll/arrowscroll/TallTextAboveButtonTest.java
+++ b/core/tests/coretests/src/android/widget/scroll/arrowscroll/TallTextAboveButtonTest.java
@@ -16,13 +16,13 @@
 
 package android.widget.scroll.arrowscroll;
 
-import android.widget.scroll.TallTextAboveButton;
-
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.ScrollView;
 import android.widget.TextView;
+import android.widget.scroll.TallTextAboveButton;
+
+import androidx.test.filters.MediumTest;
 
 public class TallTextAboveButtonTest extends ActivityInstrumentationTestCase<TallTextAboveButton> {
     private ScrollView mScrollView;
diff --git a/core/tests/coretests/src/android/widget/touchmode/ChangeTouchModeTest.java b/core/tests/coretests/src/android/widget/touchmode/ChangeTouchModeTest.java
index 449c95c..aa20c9b 100644
--- a/core/tests/coretests/src/android/widget/touchmode/ChangeTouchModeTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/ChangeTouchModeTest.java
@@ -16,16 +16,17 @@
 
 package android.widget.touchmode;
 
-import android.widget.layout.linear.LLOfButtons1;
-import android.widget.layout.linear.LLOfButtons2;
 import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
-import static android.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
 import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
+import static android.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
+import android.widget.layout.linear.LLOfButtons1;
+import android.widget.layout.linear.LLOfButtons2;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 /**
  * Tests that the touch mode changes from various events, and that the state
diff --git a/core/tests/coretests/src/android/widget/touchmode/FocusableInTouchModeClickTest.java b/core/tests/coretests/src/android/widget/touchmode/FocusableInTouchModeClickTest.java
index 691b25a..97c982f 100644
--- a/core/tests/coretests/src/android/widget/touchmode/FocusableInTouchModeClickTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/FocusableInTouchModeClickTest.java
@@ -16,12 +16,12 @@
 
 package android.widget.touchmode;
 
-import android.widget.layout.linear.LLOfTwoFocusableInTouchMode;
-
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.layout.linear.LLOfTwoFocusableInTouchMode;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
 
 public class FocusableInTouchModeClickTest extends ActivityInstrumentationTestCase2<LLOfTwoFocusableInTouchMode> {
 
diff --git a/core/tests/coretests/src/android/widget/touchmode/StartInTouchWithViewInFocusTest.java b/core/tests/coretests/src/android/widget/touchmode/StartInTouchWithViewInFocusTest.java
index 5339188..88aa9ca 100644
--- a/core/tests/coretests/src/android/widget/touchmode/StartInTouchWithViewInFocusTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/StartInTouchWithViewInFocusTest.java
@@ -16,14 +16,15 @@
 
 package android.widget.touchmode;
 
-import android.widget.layout.linear.LLEditTextThenButton;
 import static android.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.layout.linear.LLEditTextThenButton;
+
+import androidx.test.filters.MediumTest;
 
 public class StartInTouchWithViewInFocusTest extends 
         ActivityInstrumentationTestCase2<LLEditTextThenButton> {
diff --git a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusChangeTest.java b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusChangeTest.java
index 5a6110c..f192f68 100644
--- a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusChangeTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusChangeTest.java
@@ -21,11 +21,11 @@
 import static android.util.TouchModeFlexibleAsserts.assertNotInTouchModeAfterKey;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.layout.linear.LLOfButtons1;
 
+import androidx.test.filters.MediumTest;
 
 /**
  * Make sure focus isn't kept by buttons when entering touch mode.
diff --git a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
index 3ddeef0..87f33a4c 100644
--- a/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
+++ b/core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
@@ -20,12 +20,13 @@
 import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
 
 import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.layout.linear.LLEditTextThenButton;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+
 /**
  * Some views, like edit texts, can keep and gain focus even when in touch mode.
  */
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index a302657..aadfcbc 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -57,7 +57,6 @@
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.Voice;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
 import android.text.TextUtils;
 import android.view.Window;
@@ -66,6 +65,8 @@
 import android.view.accessibility.IAccessibilityManager;
 import android.widget.Toast;
 
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkObjectProvider;
 import com.android.internal.util.test.FakeSettingsProvider;
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1859378..aaa624e 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,6 +16,30 @@
 
 package com.android.internal.app;
 
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.usage.UsageStatsManager;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 
@@ -25,32 +49,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-import android.app.usage.UsageStats;
-import android.app.usage.UsageStatsManager;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.times;
 
 /**
  * Chooser activity instrumentation tests
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index c446f3c..60529f6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -16,14 +16,14 @@
 
 package com.android.internal.app;
 
+import static org.mockito.Mockito.mock;
+
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 
 import java.util.function.Function;
 
-import static org.mockito.Mockito.mock;
-
 public class ChooserWrapperActivity extends ChooserActivity {
     /*
      * Simple wrapper around chooser activity to be able to initiate it under test
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index cfb6bdd..9b13af2 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -46,9 +46,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 404c99c..fe2fb85 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -16,6 +16,29 @@
 
 package com.android.internal.app;
 
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 import com.android.internal.widget.ResolverDrawerLayout;
@@ -26,37 +49,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
-import android.app.usage.UsageStats;
-import android.app.usage.UsageStatsManager;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.View;
-import android.widget.RelativeLayout;
-
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
-
-import static android.os.SystemClock.sleep;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 /**
  * Resolver activity instrumentation tests
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
index c710b9a..850b466 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
@@ -23,10 +23,6 @@
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
 /**
  * Utility class used by resolver tests to create mock data
  */
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
index 284ab60..fcec00e 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverListControllerTest.java
@@ -25,34 +25,31 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
-
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.Intent;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 
-import java.io.File;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index 163211e..83f6bc2 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -16,17 +16,12 @@
 
 package com.android.internal.app;
 
-import android.app.usage.UsageStatsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-
-import java.util.function.Function;
-
 import static org.mockito.Mockito.mock;
 
+import android.app.usage.UsageStatsManager;
+import android.content.pm.PackageManager;
+
+import java.util.function.Function;
 
 /*
  * Simple wrapper around chooser activity to be able to initiate it under test
diff --git a/core/tests/coretests/src/com/android/internal/app/WindowDecorActionBarTest.java b/core/tests/coretests/src/com/android/internal/app/WindowDecorActionBarTest.java
index 472958a..87ad124 100644
--- a/core/tests/coretests/src/com/android/internal/app/WindowDecorActionBarTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/WindowDecorActionBarTest.java
@@ -17,12 +17,13 @@
 package com.android.internal.app;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.ActionMode;
 import android.view.Menu;
 import android.view.MenuItem;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests for {@link WindowDecorActionBar}.
  */
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
index 115af5e..f7fea3b 100644
--- a/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
@@ -16,20 +16,14 @@
 
 package com.android.internal.app.procstats;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-
-import android.os.BatteryStats;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
-import org.mockito.Mockito;
-
 /**
  * Provides test cases for SparseMappingTable.
  */
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java
index 629f7b6..222e494 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodDebugTest.java
@@ -18,10 +18,11 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.WindowManager.LayoutParams;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java
index 8179328..ba63908 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/SubtypeLocaleUtilsTest.java
@@ -18,8 +18,8 @@
 
 import static org.junit.Assert.assertEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
index 992b46f..b687801 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
@@ -13,6 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
@@ -20,10 +21,11 @@
 import android.app.ActivityManager;
 import android.os.BatteryStats;
 import android.os.WorkSource;
-import android.support.test.filters.SmallTest;
 import android.util.ArrayMap;
 import android.view.Display;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 /**
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
index 08f8dd1..37f818a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
@@ -13,11 +13,13 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index ee8d508..0179ead 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
@@ -36,11 +37,12 @@
 
 import android.os.BatteryStats;
 import android.os.UserHandle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseLongArray;
 import android.view.Display;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.Before;
@@ -64,7 +66,7 @@
  * Install: adb install -r \
  * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsCpuTimesTest -w \
- * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  *
  * or
  *
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java
index 3a5a9f5..efb8710 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDualTimerTest.java
@@ -13,10 +13,12 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.os.BatteryStats;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
index 19dab79..a42286f 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsDurationTimerTest.java
@@ -13,11 +13,13 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
index 7467114..355601c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
@@ -17,7 +17,6 @@
 
 package com.android.internal.os;
 
-
 import static android.os.BatteryStats.Uid.PROCESS_STATE_TOP;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -37,12 +36,13 @@
 import android.content.pm.PackageManager;
 import android.os.BatteryStats;
 import android.os.Process;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.text.format.DateUtils;
 import android.util.StatsLog;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import junit.framework.TestCase;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
index 10a3189..cc0ddb7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryTest.java
@@ -13,18 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import static org.junit.Assert.assertEquals;
-
 import android.content.Context;
 import android.os.Parcel;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 613de45..dc93675 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
@@ -31,12 +32,13 @@
 import static org.mockito.Mockito.when;
 
 import android.os.BatteryStats;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.Display;
 
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 8cbe5d6..3e33273 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -13,6 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import static android.os.BatteryStats.STATS_CURRENT;
@@ -20,21 +21,20 @@
 import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
 
 import android.app.ActivityManager;
-import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.BatteryStats.HistoryItem;
 import android.os.BatteryStats.Uid.Sensor;
 import android.os.WorkSource;
-import android.support.test.filters.SmallTest;
 import android.view.Display;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.internal.os.BatteryStatsImpl.DualTimer;
 import com.android.internal.os.BatteryStatsImpl.Uid;
+
 import junit.framework.TestCase;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -47,7 +47,7 @@
  * Install: adb install -r \
  *      ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsNoteTest -w \
- *      com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ *      com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  */
 public class BatteryStatsNoteTest extends TestCase {
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
index 251ceb0..61d20df 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java
@@ -13,11 +13,13 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index a751f90..b851f0a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -13,13 +13,15 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.app.ActivityManager;
 import android.os.BatteryStats;
-import android.support.test.filters.SmallTest;
 import android.view.Display;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 /**
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
index 5fd8225..b9995c4 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java
@@ -18,7 +18,8 @@
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.Assert;
 import junit.framework.TestCase;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsStopwatchTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsStopwatchTimerTest.java
index 015314e..f76f316 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsStopwatchTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsStopwatchTimerTest.java
@@ -13,10 +13,12 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
 import android.os.BatteryStats;
-import android.support.test.filters.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index 225515e..d69e1d1 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
index 3190d9e..bce8b40 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java
@@ -16,19 +16,20 @@
 
 package com.android.internal.os;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
 import android.util.Log;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.Assert;
 import junit.framework.TestCase;
 
 import org.mockito.Mockito;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 /**
  * Provides test cases for android.os.BatteryStats.
  */
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
index 98d0f7f..87dc2f3 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java
@@ -18,16 +18,17 @@
 
 import android.os.BatteryStats;
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
 import android.util.StringBuilderPrinter;
 
-import junit.framework.Assert;
-import junit.framework.TestCase;
+import androidx.test.filters.SmallTest;
 
 import com.android.internal.os.BatteryStatsImpl.Clocks;
 import com.android.internal.os.BatteryStatsImpl.TimeBase;
 import com.android.internal.os.BatteryStatsImpl.Timer;
 
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
 /**
  * Provides test cases for android.os.BatteryStats.
  */
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java
index a7e75a2..4df3190 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUidTest.java
@@ -16,22 +16,10 @@
 
 package com.android.internal.os;
 
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
+import androidx.test.filters.SmallTest;
 
-import android.os.BatteryStats;
-import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.Assert;
 import junit.framework.TestCase;
 
-import com.android.internal.os.BatteryStatsImpl;
-
-import org.mockito.Mockito;
-
 /**
  * Provides test cases for android.os.BatteryStats.
  */
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
index 450473d..e7a1bca 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsUserLifecycleTests.java
@@ -28,12 +28,13 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.util.ArraySet;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index dc3a12f..1d35143 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -22,11 +22,12 @@
 import android.os.Binder;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.BinderInternal.CallSession;
 
 import org.junit.Assert;
diff --git a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
index 42c9139..01515bd 100644
--- a/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BstatsCpuTimesValidationTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static android.os.BatteryStats.UID_TIMES_TYPE_ALL;
@@ -33,9 +34,6 @@
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
-import com.android.frameworks.coretests.aidl.ICmdCallback;
-import com.android.frameworks.coretests.aidl.ICmdReceiver;
-
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
 import android.content.ComponentName;
@@ -52,14 +50,18 @@
 import android.os.Process;
 import android.os.SystemClock;
 import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.support.test.uiautomator.UiDevice;
 import android.text.TextUtils;
 import android.util.DebugUtils;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.aidl.ICmdCallback;
+import com.android.frameworks.coretests.aidl.ICmdReceiver;
+
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Rule;
diff --git a/core/tests/coretests/src/com/android/internal/os/DebugTest.java b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
index efb78d7..2a8a857 100644
--- a/core/tests/coretests/src/com/android/internal/os/DebugTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/DebugTest.java
@@ -18,7 +18,8 @@
 
 import android.os.Debug;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 @SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
index 8360126..a25a7489 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
@@ -24,9 +24,10 @@
 import android.content.Context;
 import android.os.FileUtils;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
index 2663f2b..7a31605 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
@@ -24,9 +24,10 @@
 import android.content.Context;
 import android.os.FileUtils;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
new file mode 100644
index 0000000..c03d1f3
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.SystemClock;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.KernelCpuThreadReader.ProcessCpuUsage;
+import com.android.internal.os.KernelCpuThreadReader.ThreadCpuUsage;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.OptionalDouble;
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * End to end test for {@link KernelCpuThreadReader} that checks the accuracy of the reported times
+ * by spawning threads that do a predictable amount of work
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class KernelCpuThreadReaderEndToEndTest {
+
+    private static final int TIMED_NUM_SAMPLES = 5;
+    private static final int TIMED_START_MILLIS = 500;
+    private static final int TIMED_END_MILLIS = 2000;
+    private static final int TIMED_INCREMENT_MILLIS = 500;
+    private static final int TIMED_COMPARISON_DELTA_MILLIS = 200;
+
+    private static final int ITERATIVE_NUM_SAMPLES = 100;
+    private static final long ITERATIVE_LOW_ITERATIONS = (long) 1e8;
+    private static final long ITERATIVE_HIGH_ITERATIONS = (long) 2e8;
+    private static final double ITERATIONS_COMPARISONS_DELTA = 0.25;
+
+    /**
+     * Test that when we busy-wait for the thread-local time to reach N seconds, the time reported
+     * is also N seconds. Takes ~10s.
+     */
+    @Test
+    public void testTimedWork() throws InterruptedException {
+        for (int millis = TIMED_START_MILLIS;
+                millis <= TIMED_END_MILLIS;
+                millis += TIMED_INCREMENT_MILLIS) {
+            final Duration targetDuration = Duration.ofMillis(millis);
+            final Runnable work = timedWork(targetDuration);
+            Duration resultDuration = getAverageWorkTime(
+                    work, String.format("timed%dms", millis), TIMED_NUM_SAMPLES);
+            assertEquals(
+                    "Time worked according to currentThreadTimeMillis doesn't match "
+                            + "KernelCpuThreadReader",
+                    targetDuration.toMillis(), resultDuration.toMillis(),
+                    TIMED_COMPARISON_DELTA_MILLIS);
+        }
+    }
+
+    /**
+     * Test that when we scale up the amount of work by N, the time reported also scales by N. Takes
+     * ~15s.
+     */
+    @Test
+    public void testIterativeWork() throws InterruptedException {
+        final Runnable lowAmountWork = iterativeWork(ITERATIVE_LOW_ITERATIONS);
+        final Runnable highAmountWork = iterativeWork(ITERATIVE_HIGH_ITERATIONS);
+        final Duration lowResultDuration =
+                getAverageWorkTime(lowAmountWork, "iterlow", ITERATIVE_NUM_SAMPLES);
+        final Duration highResultDuration =
+                getAverageWorkTime(highAmountWork, "iterhigh", ITERATIVE_NUM_SAMPLES);
+        assertEquals(
+                "Work scale and CPU time scale do not match",
+                ((double) ITERATIVE_HIGH_ITERATIONS) / ((double) ITERATIVE_LOW_ITERATIONS),
+                ((double) highResultDuration.toMillis()) / ((double) lowResultDuration.toMillis()),
+                ITERATIONS_COMPARISONS_DELTA);
+    }
+
+    /**
+     * Run some work {@code numSamples} times, and take the average CPU duration used for that work
+     * according to {@link KernelCpuThreadReader}
+     */
+    private Duration getAverageWorkTime(
+            Runnable work, String tag, int numSamples) throws InterruptedException {
+        // Count down every time a thread finishes work, so that we can wait for work to complete
+        final CountDownLatch workFinishedLatch = new CountDownLatch(numSamples);
+        // Count down once when threads can terminate (after we get them from
+        // `KernelCpuThreadReader`)
+        final CountDownLatch threadFinishedLatch = new CountDownLatch(1);
+
+        // Start `NUM_SAMPLE` threads to do the work
+        for (int i = 0; i < numSamples; i++) {
+            final String threadName = String.format("%s%d", tag, i);
+            // Check the thread name, as we rely on it later to identify threads
+            assertTrue("Max name length for linux threads is 15", threadName.length() <= 15);
+            doWork(work, threadName, workFinishedLatch, threadFinishedLatch);
+        }
+
+        // Wait for threads to finish
+        workFinishedLatch.await();
+
+        // Get thread data from KernelCpuThreadReader
+        final KernelCpuThreadReader kernelCpuThreadReader = KernelCpuThreadReader.create();
+        assertNotNull(kernelCpuThreadReader);
+        final ProcessCpuUsage currentProcessCpuUsage =
+                kernelCpuThreadReader.getCurrentProcessCpuUsage();
+
+        // Threads can terminate, as we've finished crawling them from /proc
+        threadFinishedLatch.countDown();
+
+        // Check that we've got times for every thread we spawned
+        final List<ThreadCpuUsage> threadCpuUsages = currentProcessCpuUsage.threadCpuUsages
+                .stream()
+                .filter((thread) -> thread.threadName.startsWith(tag))
+                .collect(Collectors.toList());
+        assertEquals(
+                "Incorrect number of threads returned by KernelCpuThreadReader",
+                numSamples, threadCpuUsages.size());
+
+        // Calculate the average time spent working
+        final OptionalDouble averageWorkTimeMillis = threadCpuUsages.stream()
+                .mapToDouble((t) -> Arrays.stream(t.usageTimesMillis).sum())
+                .average();
+        assertTrue(averageWorkTimeMillis.isPresent());
+        return Duration.ofMillis((long) averageWorkTimeMillis.getAsDouble());
+    }
+
+    /**
+     * Work that lasts {@code duration} according to {@link SystemClock#currentThreadTimeMillis()}
+     */
+    private Runnable timedWork(Duration duration) {
+        return () -> {
+            // Busy loop until `duration` has elapsed for the thread timer
+            final long startTimeMillis = SystemClock.currentThreadTimeMillis();
+            final long durationMillis = duration.toMillis();
+            while (true) {
+                final long elapsedMillis = SystemClock.currentThreadTimeMillis() - startTimeMillis;
+                if (elapsedMillis >= durationMillis) {
+                    break;
+                }
+            }
+        };
+    }
+
+    /**
+     * Work that iterates {@code iterations} times
+     */
+    private Runnable iterativeWork(long iterations) {
+        Consumer<Long> empty = (i) -> {
+        };
+        return () -> {
+            long count = 0;
+            for (long i = 0; i < iterations; i++) {
+                // Alternate branching to reduce effect of branch prediction
+                if (i % 2 == 0) {
+                    count++;
+                }
+            }
+            // Call empty function with value to avoid loop getting optimized away
+            empty.accept(count);
+        };
+    }
+
+    /**
+     * Perform some work in another thread
+     *
+     * @param work                the work to perform
+     * @param threadName          the name of the spawned thread
+     * @param workFinishedLatch   latch to register that the work has been completed
+     * @param threadFinishedLatch latch to pause termination of the thread until the latch is
+     *                            decremented
+     */
+    private void doWork(
+            Runnable work,
+            String threadName,
+            CountDownLatch workFinishedLatch,
+            CountDownLatch threadFinishedLatch) {
+        Runnable workWrapped = () -> {
+            // Do the work
+            work.run();
+            // Notify that the work is finished
+            workFinishedLatch.countDown();
+            // Wait until `threadFinishLatch` has been released in order to keep the thread alive so
+            // we can see it in `proc` filesystem
+            try {
+                threadFinishedLatch.await();
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        };
+        new Thread(workWrapped, threadName).start();
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
index b242a34..0c56b8a 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -23,9 +23,10 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
index adafda0..1b13a99 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static org.junit.Assert.assertEquals;
@@ -20,11 +21,12 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseLongArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
 
 import org.junit.After;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
index ad20d84..2ea80da 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -22,11 +23,12 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
 
 import org.junit.After;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
index 1d3a98a..0b6fed3 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -24,11 +25,12 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 
 import org.junit.After;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
index 9b4512b..8f81ea2 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidUserSysTimeReaderTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.os;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -23,11 +24,12 @@
 import android.content.Context;
 import android.os.FileUtils;
 import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 
 import org.junit.After;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java b/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
index 32317ee..60dac85 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelMemoryBandwidthStatsTest.java
@@ -1,11 +1,27 @@
+/*
+ * 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.
+ */
+
 package com.android.internal.os;
 
-import android.support.test.filters.SmallTest;
 import android.util.LongSparseLongArray;
 
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
-import org.junit.Assert;
 import org.mockito.Mockito;
 
 import java.io.BufferedReader;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index 29227f9..479e19e 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -21,10 +21,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.internal.os.KernelSingleUidTimeReader.Injector;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
index 28570e8..12f6c18 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
@@ -20,8 +20,8 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
index 85dce02..532f337 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
@@ -21,10 +21,11 @@
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
index 67c4e61..6d2980b 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -24,10 +24,11 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,7 +54,7 @@
  * Install: adb install -r \
  * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.KernelUidCpuFreqTimeReaderTest -w \
- * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ * com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  *
  * or
  *
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
index 4e4bb3507..78b6843 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelWakelockReaderTest.java
@@ -13,9 +13,10 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.os;
 
-import android.support.test.filters.SmallTest;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java b/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
index fe62764..cb8a62c 100644
--- a/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LoggingPrintStreamTest.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.os;
 
-import android.test.suitebuilder.annotation.Suppress;
+import androidx.test.filters.Suppress;
+
+import junit.framework.TestCase;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -25,8 +27,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import junit.framework.TestCase;
-
 // this test causes a IllegalAccessError: superclass not accessible
 @Suppress
 public class LoggingPrintStreamTest extends TestCase {
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
index 37b4e41a..0516bb7 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -30,8 +30,9 @@
 import static org.mockito.Mockito.when;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -55,7 +56,7 @@
  * Install: adb install -r \
  *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
- *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ *     com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
index 853bf8a..d2f5735 100644
--- a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterTest.java
@@ -28,8 +28,9 @@
 import static org.mockito.Mockito.when;
 
 import android.os.Parcel;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index b65c1e6..2c597b1 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -23,8 +23,9 @@
 import android.os.Looper;
 import android.os.Message;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Assert;
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index b68f6b1..c18445e 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -21,6 +21,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.location.gnssmetrics.GnssMetrics;
+
 import java.util.ArrayList;
 import java.util.Queue;
 import java.util.concurrent.Future;
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/PowerCalculatorTest.java
index 14d62e0..c592ab6 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerCalculatorTest.java
@@ -17,13 +17,13 @@
 
 package com.android.internal.os;
 
-
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.os.BatteryStats;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
index 2853c96..5862368 100644
--- a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
@@ -17,8 +17,8 @@
 
 package com.android.internal.os;
 
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 
 import junit.framework.TestCase;
 
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java b/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
index 489e164..e97caf8 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcStatsUtilTest.java
@@ -20,9 +20,10 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java b/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
index 2893066..9db3f8a 100644
--- a/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ProcTimeInStateReaderTest.java
@@ -22,9 +22,10 @@
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
index c051a1c..85eafc5 100644
--- a/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/StoragedUidIoStatsReaderTest.java
@@ -15,15 +15,17 @@
  */
 
 package com.android.internal.os;
+
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
 import org.junit.Before;
@@ -36,7 +38,6 @@
 import java.io.File;
 import java.nio.file.Files;
 
-
 /**
  * Test class for {@link StoragedUidIoStatsReader}.
  *
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
index 2a24881..8e0c1fe 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
@@ -17,8 +17,6 @@
 package com.android.internal.policy;
 
 import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
 import android.view.KeyEvent;
@@ -32,7 +30,8 @@
 import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 
-import java.util.List;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
 
 /**
  * Tests {@link PhoneWindow}'s {@link ActionMode} related methods.
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
index d4b8566..6c2d630 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowTest.java
@@ -28,12 +28,13 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.ActionMode;
 import android.view.ContextThemeWrapper;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
index b3897ce..d026735 100644
--- a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -13,9 +13,11 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
+
 package com.android.internal.util;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
+
 import junit.framework.TestCase;
 
 import java.util.ArrayList;
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
index a44b860..4716312 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.util;
 
 import static com.android.internal.util.DumpUtils.CRITICAL_SECTION_COMPONENTS;
diff --git a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
index 4845c4e..b2a2265 100644
--- a/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/LineBreakBufferedWriterTest.java
@@ -19,11 +19,8 @@
 import junit.framework.TestCase;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
 import java.io.Writer;
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 
 /**
diff --git a/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
index f00c48c..867152e 100644
--- a/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ParseUtilsTest.java
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package com.android.internal.util;
 
 import junit.framework.TestCase;
diff --git a/core/tests/coretests/src/android/util/TokenBucketTest.java b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
similarity index 90%
rename from core/tests/coretests/src/android/util/TokenBucketTest.java
rename to core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
index f7ac20c..6c50bce 100644
--- a/core/tests/coretests/src/android/util/TokenBucketTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/TokenBucketTest.java
@@ -18,6 +18,7 @@
 
 import android.os.SystemClock;
 import android.text.format.DateUtils;
+
 import junit.framework.TestCase;
 
 public class TokenBucketTest extends TestCase {
@@ -54,9 +55,9 @@
 
         drain(new TokenBucket(FILL_DELTA_VERY_LONG, 10, 100), 10);
 
-        drain(new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50), 50);
-        drain(new TokenBucket((int)DateUtils.HOUR_IN_MILLIS, 10), 10);
-        drain(new TokenBucket((int)DateUtils.DAY_IN_MILLIS, 200), 200);
+        drain(new TokenBucket((int) DateUtils.MINUTE_IN_MILLIS, 50), 50);
+        drain(new TokenBucket((int) DateUtils.HOUR_IN_MILLIS, 10), 10);
+        drain(new TokenBucket((int) DateUtils.DAY_IN_MILLIS, 200), 200);
     }
 
     public void testReset() {
@@ -163,16 +164,16 @@
 
     void assertDuration(long expected, long elapsed) {
         String msg = String.format(
-            "expected elapsed time at least %d ms, but was %d ms", expected, elapsed);
+                "expected elapsed time at least %d ms, but was %d ms", expected, elapsed);
         elapsed += 1; // one millisecond extra guard
         assertTrue(msg, elapsed >= expected);
     }
 
-    void assertThrow(Fn fn)     {
-      try {
-          fn.call();
-          fail("expected n exception to be thrown.");
-      } catch (Throwable t) {}
+    void assertThrow(Fn fn) {
+        try {
+            fn.call();
+            fail("expected n exception to be thrown.");
+        } catch (Throwable t) { }
     }
 
     interface Fn { void call(); }
diff --git a/core/tests/coretests/src/com/android/internal/widget/ActionBarContainerTest.java b/core/tests/coretests/src/com/android/internal/widget/ActionBarContainerTest.java
index 912b7ec..b372366 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ActionBarContainerTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ActionBarContainerTest.java
@@ -18,11 +18,12 @@
 
 import android.content.Context;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.view.ActionMode;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests for {@link ActionBarContainer}.
  */
diff --git a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
index d782c0c..d10f173 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ActionBarOverlayLayoutTest.java
@@ -29,9 +29,6 @@
 import android.content.Context;
 import android.graphics.Insets;
 import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
 import android.view.DisplayCutout;
 import android.view.View;
 import android.view.View.OnApplyWindowInsetsListener;
@@ -40,6 +37,10 @@
 import android.widget.FrameLayout;
 import android.widget.Toolbar;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
index e21143d..0fada06 100644
--- a/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
@@ -32,10 +32,11 @@
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.support.test.InstrumentationRegistry;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.Before;
 import org.junit.Test;
 
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
index 1806b22..2e0dbb4 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -19,12 +19,13 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
 import android.text.Layout;
 import android.view.View.MeasureSpec;
 import android.widget.TextView;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
index f73950a..6167c4b 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
@@ -20,8 +20,9 @@
 import static org.junit.Assert.assertTrue;
 
 import android.os.UserHandle;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
index 41082b7..6af7c88 100644
--- a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -21,12 +21,12 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.text.Layout;
 import android.view.LayoutInflater;
 import android.view.View.MeasureSpec;
 
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.coretests.R;
 
 import org.junit.Before;
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 0dd9d09..28a8afe 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -318,6 +318,27 @@
             mMaxVolume = maxVolume;
             mIsMute = isMute;
         }
+
+        @Override
+        public void setSystemAudioModeOnForAudioOnlySource() {
+        }
+
+        @Override
+        public int getPhysicalAddress() {
+            return 0x0000;
+        }
+
+        @Override
+        public void powerOffRemoteDevice(int logicalAddress, int powerStatus) {
+        }
+
+        @Override
+        public void powerOnRemoteDevice(int logicalAddress, int powerStatus) {
+        }
+
+        @Override
+        public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
+        }
     }
 
 }
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
index f3d98a8..afbcd46 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk
@@ -23,7 +23,7 @@
 LOCAL_PACKAGE_NAME := MultiDexLegacyTestServicesTests2
 
 LOCAL_JAVA_LIBRARIES := android-support-multidex
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
 
 LOCAL_SDK_VERSION := 9
 
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml
index 0ab2959..01285e7 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml
@@ -7,7 +7,7 @@
     <uses-sdk android:minSdkVersion="9" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.framework.multidexlegacytestservices" />
 
     <application
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java
index 900f203..f2c72f0 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java
@@ -19,22 +19,26 @@
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.util.concurrent.TimeoutException;
-import junit.framework.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
 
 /**
  * Run the tests with: <code>adb shell am instrument -w
- * com.android.framework.multidexlegacytestservices.test2/android.support.test.runner.AndroidJUnitRunner
+ * com.android.framework.multidexlegacytestservices.test2/androidx.test.runner.AndroidJUnitRunner
  * </code>
  */
 @RunWith(AndroidJUnit4.class)
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index 6ce8148..035ee10 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -39,9 +39,6 @@
     name: "privapp-permissions-platform.xml",
     sub_dir: "permissions",
     src: "privapp-permissions-platform.xml",
-    required: [
-        "privapp_whitelist_com.android.settings.intelligence",
-    ],
 }
 
 prebuilt_etc {
@@ -86,6 +83,7 @@
 
 prebuilt_etc {
     name: "privapp_whitelist_com.android.settings.intelligence",
+    product_specific: true,
     sub_dir: "permissions",
     src: "com.android.settings.intelligence.xml",
     filename_from_src: true,
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 4a2db0a..fb43e41 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -223,12 +223,12 @@
          code to link against. -->
 
     <library name="android.test.base"
-            file="/system/framework/android.test.base.impl.jar" />
+            file="/system/framework/android.test.base.jar" />
     <library name="android.test.mock"
-            file="/system/framework/android.test.mock.impl.jar"
+            file="/system/framework/android.test.mock.jar"
             dependency="android.test.base" />
     <library name="android.test.runner"
-            file="/system/framework/android.test.runner.impl.jar"
+            file="/system/framework/android.test.runner.jar"
             dependency="android.test.base:android.test.mock" />
 
     <!-- In BOOT_JARS historically, and now added to legacy applications. -->
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 3342fd2..cbb780d 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -17,12 +17,14 @@
 package android.graphics;
 
 import android.annotation.ColorInt;
+import android.annotation.ColorLong;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Px;
 import android.annotation.Size;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.graphics.fonts.FontVariationAxis;
 import android.os.Build;
@@ -972,6 +974,31 @@
     }
 
     /**
+     * Set the paint's color with a {@link ColorLong}. Note that the color is
+     * a long with an encoded {@link ColorSpace} as well as alpha and r,g,b.
+     * These values are not premultiplied, meaning that alpha can be any value,
+     * regardless of the values of r,g,b. See the {@link Color} class for more
+     * details.
+     *
+     * @param color The new color (including alpha and {@link ColorSpace})
+     *      to set in the paint.
+     * @throws IllegalArgumentException if the color space encoded in the long
+     *      is invalid or unknown.
+     *
+     * @hide pending API approval
+     */
+    @TestApi
+    public void setColor(@ColorLong long color) {
+        ColorSpace cs = Color.colorSpace(color);
+        float r = Color.red(color);
+        float g = Color.green(color);
+        float b = Color.blue(color);
+        float a = Color.alpha(color);
+
+        nSetColor(mNativePaint, cs, r, g, b, a);
+    }
+
+    /**
      * Helper to getColor() that just returns the color's alpha value. This is
      * the same as calling getColor() >>> 24. It always returns a value between
      * 0 (completely transparent) and 255 (completely opaque).
@@ -1370,12 +1397,45 @@
      * The alpha of the shadow will be the paint's alpha if the shadow color is
      * opaque, or the alpha from the shadow color if not.
      */
-    public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
-      mShadowLayerRadius = radius;
-      mShadowLayerDx = dx;
-      mShadowLayerDy = dy;
-      mShadowLayerColor = shadowColor;
-      nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
+    public void setShadowLayer(float radius, float dx, float dy, @ColorInt int shadowColor) {
+        mShadowLayerRadius = radius;
+        mShadowLayerDx = dx;
+        mShadowLayerDy = dy;
+        mShadowLayerColor = shadowColor;
+        // FIXME: Share a single native method with the ColorLong version.
+        nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
+    }
+
+    /**
+     * This draws a shadow layer below the main layer, with the specified
+     * offset and color, and blur radius. If radius is 0, then the shadow
+     * layer is removed.
+     * <p>
+     * Can be used to create a blurred shadow underneath text. Support for use
+     * with other drawing operations is constrained to the software rendering
+     * pipeline.
+     * <p>
+     * The alpha of the shadow will be the paint's alpha if the shadow color is
+     * opaque, or the alpha from the shadow color if not.
+     *
+     * @throws IllegalArgumentException if the color space encoded in the long
+     *      is invalid or unknown.
+     *
+     * @hide pending API approval
+     */
+    @TestApi
+    public void setShadowLayer(float radius, float dx, float dy, @ColorLong long shadowColor) {
+        ColorSpace cs = Color.colorSpace(shadowColor);
+        float r = Color.red(shadowColor);
+        float g = Color.green(shadowColor);
+        float b = Color.blue(shadowColor);
+        float a = Color.alpha(shadowColor);
+        nSetShadowLayer(mNativePaint, radius, dx, dy, cs, r, g, b, a);
+
+        mShadowLayerRadius = radius;
+        mShadowLayerDx = dx;
+        mShadowLayerDy = dy;
+        mShadowLayerColor = Color.toArgb(shadowColor);
     }
 
     /**
@@ -2906,6 +2966,11 @@
             int contextStart, int contextEnd, boolean isRtl, int offset);
     private static native int nGetOffsetForAdvance(long paintPtr, char[] text, int start, int end,
             int contextStart, int contextEnd, boolean isRtl, float advance);
+    private static native void nSetColor(long paintPtr, ColorSpace cs,
+            float r, float g, float b, float a);
+    private static native void nSetShadowLayer(long paintPtr,
+            float radius, float dx, float dy, ColorSpace cs,
+            float r, float g, float b, float a);
 
 
     // ---------------- @FastNative ------------------------
@@ -2961,7 +3026,7 @@
             int mMinikinLocaleListId);
     @CriticalNative
     private static native void nSetShadowLayer(long paintPtr,
-            float radius, float dx, float dy, int color);
+            float radius, float dx, float dy, @ColorInt int color);
     @CriticalNative
     private static native boolean nHasShadowLayer(long paintPtr);
     @CriticalNative
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 3dc1f2c..18d74ef 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -286,6 +286,7 @@
     value.dataType = Res_value::TYPE_NULL;
     value.data = Res_value::DATA_NULL_UNDEFINED;
     config.density = 0;
+    uint32_t source_style_resid = 0;
 
     // Try to find a value for this attribute...  we prioritize values
     // coming from, first XML attributes, then XML style, then default
@@ -309,6 +310,7 @@
         cookie = entry->cookie;
         type_set_flags = style_flags;
         value = entry->value;
+        source_style_resid = entry->style;
         if (kDebugStyles) {
           ALOGI("-> From style: type=0x%x, data=0x%08x, style=0x%08x", value.dataType, value.data,
               entry->style);
@@ -325,8 +327,10 @@
         type_set_flags = def_style_flags;
         value = entry->value;
         if (kDebugStyles) {
-          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
+          ALOGI("-> From def style: type=0x%x, data=0x%08x, style=0x%08x", value.dataType, value.data,
+              entry->style);
         }
+        source_style_resid = entry->style;
       }
     }
 
@@ -382,6 +386,7 @@
     out_values[STYLE_RESOURCE_ID] = resid;
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
+    out_values[SYTLE_SOURCE_STYLE] = source_style_resid;
 
     if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) {
       indices_idx++;
diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h
index 35ef98d..c88004c 100644
--- a/libs/androidfw/include/androidfw/AttributeResolution.h
+++ b/libs/androidfw/include/androidfw/AttributeResolution.h
@@ -23,15 +23,17 @@
 namespace android {
 
 // Offsets into the outValues array populated by the methods below. outValues is a uint32_t
-// array, but each logical element takes up 6 uint32_t-sized physical elements.
+// array, but each logical element takes up 7 uint32_t-sized physical elements.
+// Keep these in sync with android.content.res.TypedArray java class
 enum {
-  STYLE_NUM_ENTRIES = 6,
+  STYLE_NUM_ENTRIES = 7,
   STYLE_TYPE = 0,
   STYLE_DATA = 1,
   STYLE_ASSET_COOKIE = 2,
   STYLE_RESOURCE_ID = 3,
   STYLE_CHANGING_CONFIGURATIONS = 4,
-  STYLE_DENSITY = 5
+  STYLE_DENSITY = 5,
+  SYTLE_SOURCE_STYLE = 6
 };
 
 // These are all variations of the same method. They each perform the exact same operation,
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 9170d6d..68541b4 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -86,6 +86,26 @@
     mCallbacks.gles.draw(mFunctor, mData, drawInfo);
 }
 
+void WebViewFunctor::initVk(const VkFunctorInitParams& params) {
+    ATRACE_NAME("WebViewFunctor::initVk");
+    if (!mHasContext) {
+        mHasContext = true;
+    } else {
+        return;
+    }
+    mCallbacks.vk.initialize(mFunctor, mData, params);
+}
+
+void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) {
+    ATRACE_NAME("WebViewFunctor::drawVk");
+    mCallbacks.vk.draw(mFunctor, mData, params);
+}
+
+void WebViewFunctor::postDrawVk() {
+    ATRACE_NAME("WebViewFunctor::postDrawVk");
+    mCallbacks.vk.postDraw(mFunctor, mData);
+}
+
 void WebViewFunctor::destroyContext() {
     if (mHasContext) {
         mHasContext = false;
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 1719ce7..2846cb1 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -42,6 +42,12 @@
 
         void drawGl(const DrawGlInfo& drawInfo) const { mReference.drawGl(drawInfo); }
 
+        void initVk(const VkFunctorInitParams& params) { mReference.initVk(params); }
+
+        void drawVk(const VkFunctorDrawParams& params) { mReference.drawVk(params); }
+
+        void postDrawVk() { mReference.postDrawVk(); }
+
     private:
         friend class WebViewFunctor;
 
@@ -53,6 +59,9 @@
     int id() const { return mFunctor; }
     void sync(const WebViewSyncData& syncData) const;
     void drawGl(const DrawGlInfo& drawInfo);
+    void initVk(const VkFunctorInitParams& params);
+    void drawVk(const VkFunctorDrawParams& params);
+    void postDrawVk();
     void destroyContext();
 
     sp<Handle> createHandle() {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 4338b1c..e6e6b0e 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -96,7 +96,7 @@
 
     SkASSERT(mRenderThread.getGrContext() != nullptr);
     sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
-            mRenderThread.getGrContext(), backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
+            mRenderThread.getGrContext(), backendRT, this->getSurfaceOrigin(), colorType,
             mSurfaceColorSpace, &props));
 
     SkiaPipeline::updateLighting(lightGeometry, lightInfo);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 47991069..6692922 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -39,6 +39,7 @@
               const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
               const std::vector<sp<RenderNode> >& renderNodes,
               FrameInfoVisualizer* profiler) override;
+    GrSurfaceOrigin getSurfaceOrigin() override { return kBottomLeft_GrSurfaceOrigin; }
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 2e7850d..d7faaf7 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -174,7 +174,8 @@
         SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
         SkASSERT(mRenderThread.getGrContext() != nullptr);
         node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
-                                                          SkBudgeted::kYes, info, 0, &props));
+                                                          SkBudgeted::kYes, info, 0,
+                                                          this->getSurfaceOrigin(), &props));
         if (node->getLayerSurface()) {
             // update the transform in window of the layer to reset its origin wrt light source
             // position
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index ff87313..94a699b 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -48,7 +48,7 @@
     bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
                              ErrorHandler* errorHandler) override;
 
-    SkColorType getSurfaceColorType() const { return mSurfaceColorType; }
+    SkColorType getSurfaceColorType() const override { return mSurfaceColorType; }
     sk_sp<SkColorSpace> getSurfaceColorSpace() override { return mSurfaceColorSpace; }
 
     void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 6eefed9..d54275f 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -125,8 +125,6 @@
                                              uirenderer::GlFunctorLifecycleListener* listener) {
     FunctorDrawable* functorDrawable;
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
-        // TODO(cblume) use VkFunctorDrawable instead of VkInteropFunctorDrawable here when the
-        // interop is disabled/moved.
         functorDrawable = mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(
                 functor, listener, asSkCanvas());
     } else {
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 53ffc44..9343076 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -35,6 +35,7 @@
               const Rect& contentDrawBounds, bool opaque, const LightInfo& lightInfo,
               const std::vector<sp<RenderNode> >& renderNodes,
               FrameInfoVisualizer* profiler) override;
+    GrSurfaceOrigin getSurfaceOrigin() override { return kTopLeft_GrSurfaceOrigin; }
     bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
                      FrameInfo* currentFrameInfo, bool* requireSwap) override;
     DeferredLayerUpdater* createTextureLayer() override;
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 156f74a..2f8d381 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -17,6 +17,8 @@
 #include "VkFunctorDrawable.h"
 #include <private/hwui/DrawVkInfo.h>
 
+#include "renderthread/VulkanManager.h"
+#include "renderthread/RenderThread.h"
 #include <GrBackendDrawableInfo.h>
 #include <SkImage.h>
 #include <utils/Color.h>
@@ -31,34 +33,58 @@
 namespace uirenderer {
 namespace skiapipeline {
 
-VkFunctorDrawHandler::VkFunctorDrawHandler(Functor* functor) : INHERITED(), mFunctor(functor) {}
+VkFunctorDrawHandler::VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle,
+                                           const SkMatrix& matrix, const SkIRect& clip,
+                                           const SkImageInfo& image_info)
+        : INHERITED()
+        , mFunctorHandle(functor_handle)
+        , mMatrix(matrix)
+        , mClip(clip)
+        , mImageInfo(image_info) {}
 
 VkFunctorDrawHandler::~VkFunctorDrawHandler() {
-    // TODO(cblume) Fill in the DrawVkInfo parameters.
-    (*mFunctor)(DrawVkInfo::kModePostComposite, nullptr);
+    mFunctorHandle->postDrawVk();
 }
 
 void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
     ATRACE_CALL();
+    if (!renderthread::RenderThread::isCurrent())
+        LOG_ALWAYS_FATAL("VkFunctorDrawHandler::draw not called on render thread");
 
     GrVkDrawableInfo vulkan_info;
     if (!info.getVkDrawableInfo(&vulkan_info)) {
         return;
     }
+    renderthread::VulkanManager& vk_manager =
+            renderthread::RenderThread::getInstance().vulkanManager();
+    mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams());
 
-    DrawVkInfo draw_vk_info;
-    // TODO(cblume) Fill in the rest of the parameters and test the actual call.
-    draw_vk_info.isLayer = true;
+    SkMatrix44 mat4(mMatrix);
+    VkFunctorDrawParams params{
+      .width = mImageInfo.width(),
+      .height = mImageInfo.height(),
+      .is_layer = false,  // TODO(boliu): Populate is_layer.
+      .color_space_ptr = mImageInfo.colorSpace(),
+      .clip_left = mClip.fLeft,
+      .clip_top = mClip.fTop,
+      .clip_right = mClip.fRight,
+      .clip_bottom = mClip.fBottom,
+    };
+    mat4.asColMajorf(&params.transform[0]);
+    params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
+    params.color_attachment_index = vulkan_info.fColorAttachmentIndex;
+    params.compatible_render_pass = vulkan_info.fCompatibleRenderPass;
+    params.format = vulkan_info.fFormat;
 
-    (*mFunctor)(DrawVkInfo::kModeComposite, &draw_vk_info);
+    mFunctorHandle->drawVk(params);
+
+    vulkan_info.fDrawBounds->offset.x = mClip.fLeft;
+    vulkan_info.fDrawBounds->offset.y = mClip.fTop;
+    vulkan_info.fDrawBounds->extent.width = mClip.fRight - mClip.fLeft;
+    vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop;
 }
 
 VkFunctorDrawable::~VkFunctorDrawable() {
-    if (auto lp = std::get_if<LegacyFunctor>(&mAnyFunctor)) {
-        if (lp->listener) {
-            lp->listener->onGlFunctorReleased(lp->functor);
-        }
-    }
 }
 
 void VkFunctorDrawable::onDraw(SkCanvas* /*canvas*/) {
@@ -67,16 +93,17 @@
 }
 
 std::unique_ptr<FunctorDrawable::GpuDrawHandler> VkFunctorDrawable::onSnapGpuDrawHandler(
-        GrBackendApi backendApi, const SkMatrix& matrix) {
+        GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip,
+        const SkImageInfo& image_info) {
     if (backendApi != GrBackendApi::kVulkan) {
         return nullptr;
     }
     std::unique_ptr<VkFunctorDrawHandler> draw;
     if (mAnyFunctor.index() == 0) {
-        LOG_ALWAYS_FATAL("Not implemented");
-        return nullptr;
+        return std::make_unique<VkFunctorDrawHandler>(std::get<0>(mAnyFunctor).handle, matrix, clip,
+                                                      image_info);
     } else {
-        return std::make_unique<VkFunctorDrawHandler>(std::get<1>(mAnyFunctor).functor);
+        LOG_ALWAYS_FATAL("Not implemented");
     }
 }
 
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkFunctorDrawable.h
index d6fefc1..1a53c8f 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.h
@@ -32,15 +32,18 @@
  */
 class VkFunctorDrawHandler : public FunctorDrawable::GpuDrawHandler {
 public:
-    explicit VkFunctorDrawHandler(Functor* functor);
+    VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle, const SkMatrix& matrix,
+                         const SkIRect& clip, const SkImageInfo& image_info);
     ~VkFunctorDrawHandler() override;
 
     void draw(const GrBackendDrawableInfo& info) override;
 
 private:
     typedef GpuDrawHandler INHERITED;
-
-    Functor* mFunctor;
+    sp<WebViewFunctor::Handle> mFunctorHandle;
+    const SkMatrix mMatrix;
+    const SkIRect mClip;
+    const SkImageInfo mImageInfo;
 };
 
 /**
@@ -57,7 +60,8 @@
     // SkDrawable functions:
     void onDraw(SkCanvas* canvas) override;
     std::unique_ptr<FunctorDrawable::GpuDrawHandler> onSnapGpuDrawHandler(
-            GrBackendApi backendApi, const SkMatrix& matrix) override;
+            GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip,
+            const SkImageInfo& image_info) override;
 };
 
 }  // namespace skiapipeline
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index fd824bd..abc4dbf 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -17,80 +17,61 @@
 #ifndef ANDROID_HWUI_DRAW_VK_INFO_H
 #define ANDROID_HWUI_DRAW_VK_INFO_H
 
+#include <SkColorSpace.h>
 #include <vulkan/vulkan.h>
 
 namespace android {
 namespace uirenderer {
 
-/**
- * Structure used by VulkanRenderer::callDrawVKFunction() to pass and receive data from Vulkan
- * functors.
- */
-struct DrawVkInfo {
-    // Input: current width/height of destination surface
-    int width;
-    int height;
+struct VkFunctorInitParams {
+  VkInstance instance;
+  VkPhysicalDevice physical_device;
+  VkDevice device;
+  VkQueue queue;
+  uint32_t graphics_queue_index;
+  uint32_t instance_version;
+  const char* const* enabled_instance_extension_names;
+  uint32_t enabled_instance_extension_names_length;
+  const char* const* enabled_device_extension_names;
+  uint32_t enabled_device_extension_names_length;
+  const VkPhysicalDeviceFeatures2* device_features_2;
+};
 
-    // Input: is the render target an FBO
-    bool isLayer;
+struct VkFunctorDrawParams {
+  // Input: current width/height of destination surface.
+  int width;
+  int height;
 
-    // Input: current transform matrix, in OpenGL format
-    float transform[16];
+  // Input: is the render target a FBO
+  bool is_layer;
 
-    // Input: WebView should do its main compositing draws into this. It cannot do anything that
-    // would require stopping the render pass.
-    VkCommandBuffer secondaryCommandBuffer;
+  // Input: current transform matrix
+  float transform[16];
 
-    // Input: The main color attachment index where secondaryCommandBuffer will eventually be
-    // submitted.
-    uint32_t colorAttachmentIndex;
+  // Input WebView should do its main compositing draws into this. It cannot do
+  // anything that would require stopping the render pass.
+  VkCommandBuffer secondary_command_buffer;
 
-    // Input: A render pass which will be compatible to the one which the secondaryCommandBuffer
-    // will be submitted into.
-    VkRenderPass compatibleRenderPass;
+  // Input: The main color attachment index where secondary_command_buffer will
+  // eventually be submitted.
+  uint32_t color_attachment_index;
 
-    // Input: Format of the destination surface.
-    VkFormat format;
+  // Input: A render pass which will be compatible to the one which the
+  // secondary_command_buffer will be submitted into.
+  VkRenderPass compatible_render_pass;
 
-    // Input: Color space
-    const SkColorSpace* colorSpaceInfo;
+  // Input: Format of the destination surface.
+  VkFormat format;
 
-    // Input: current clip rect
-    int clipLeft;
-    int clipTop;
-    int clipRight;
-    int clipBottom;
+  // Input: Color space.
+  const SkColorSpace* color_space_ptr;
 
-    /**
-     * Values used as the "what" parameter of the functor.
-     */
-    enum Mode {
-        // Called once at WebView start
-        kModeInit,
-        // Called when things need to be re-created
-        kModeReInit,
-        // Notifies the app that the composite functor will be called soon. This allows WebView to
-        // begin work early.
-        kModePreComposite,
-        // Do the actual composite work
-        kModeComposite,
-        // This allows WebView to begin using the previously submitted objects in future work.
-        kModePostComposite,
-        // Invoked every time the UI thread pushes over a frame to the render thread and the owning
-        // view has a dirty display list*. This is a signal to sync any data that needs to be
-        // shared between the UI thread and the render thread. During this time the UI thread is
-        // blocked.
-        kModeSync
-    };
-
-    /**
-     * Values used by Vulkan functors to tell the framework what to do next.
-     */
-    enum Status {
-        // The functor is done
-        kStatusDone = 0x0,
-    };
-};  // struct DrawVkInfo
+  // Input: current clip rect
+  int clip_left;
+  int clip_top;
+  int clip_right;
+  int clip_bottom;
+};
 
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h
index da3d06a..96da947 100644
--- a/libs/hwui/private/hwui/WebViewFunctor.h
+++ b/libs/hwui/private/hwui/WebViewFunctor.h
@@ -19,6 +19,7 @@
 
 #include <cutils/compiler.h>
 #include <private/hwui/DrawGlInfo.h>
+#include <private/hwui/DrawVkInfo.h>
 
 namespace android::uirenderer {
 
@@ -52,18 +53,12 @@
             // Called on RenderThread. initialize is guaranteed to happen before this call
             void (*draw)(int functor, void* data, const DrawGlInfo& params);
         } gles;
-        // TODO: VK support. The current DrawVkInfo is monolithic and needs to be split up for
-        // what params are valid on what callbacks
         struct {
             // Called either the first time the functor is used or the first time it's used after
             // a call to onContextDestroyed.
-            // void (*initialize)(int functor, const InitParams& params);
-            // void (*frameStart)(int functor, /* todo: what params are actually needed for this to
-            // be useful? Is this useful? */)
-            // void (*draw)(int functor, const CompositeParams& params /* todo: rename - composite
-            // almost always means something else, and we aren't compositing */);
-            // void (*frameEnd)(int functor, const PostCompositeParams& params /* todo: same as
-            // CompositeParams - rename */);
+            void (*initialize)(int functor, void* data, const VkFunctorInitParams& params);
+            void (*draw)(int functor, void* data, const VkFunctorDrawParams& params);
+            void (*postDraw)(int functor, void*);
         } vk;
     };
 };
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 42e17b273..d4dd629 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -84,6 +84,7 @@
     virtual void onPrepareTree() = 0;
     virtual SkColorType getSurfaceColorType() const = 0;
     virtual sk_sp<SkColorSpace> getSurfaceColorSpace() = 0;
+    virtual GrSurfaceOrigin getSurfaceOrigin() = 0;
 
     virtual ~IRenderPipeline() {}
 };
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 5272227..1ef83fb 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -47,6 +47,10 @@
 class RenderState;
 class TestUtils;
 
+namespace skiapipeline {
+class VkFunctorDrawHandler;
+}
+
 namespace renderthread {
 
 class CanvasContext;
@@ -124,6 +128,7 @@
     friend class DummyVsyncSource;
     friend class android::uirenderer::TestUtils;
     friend class android::uirenderer::WebViewFunctor;
+    friend class android::uirenderer::skiapipeline::VkFunctorDrawHandler;
 
     RenderThread();
     virtual ~RenderThread();
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index aa7a141..6c540f6 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -34,6 +34,23 @@
 namespace uirenderer {
 namespace renderthread {
 
+static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
+    // All Vulkan structs that could be part of the features chain will start with the
+    // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
+    // so we can get access to the pNext for the next struct.
+    struct CommonVulkanHeader {
+        VkStructureType sType;
+        void*           pNext;
+    };
+
+    void* pNext = features.pNext;
+    while (pNext) {
+        void* current = pNext;
+        pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
+        free(current);
+    }
+}
+
 #define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F)
 #define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
 #define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
@@ -66,6 +83,11 @@
     mDevice = VK_NULL_HANDLE;
     mPhysicalDevice = VK_NULL_HANDLE;
     mInstance = VK_NULL_HANDLE;
+    mInstanceVersion = 0u;
+    mInstanceExtensions.clear();
+    mDeviceExtensions.clear();
+    free_features_extensions_structs(mPhysicalDeviceFeatures2);
+    mPhysicalDeviceFeatures2 = {};
 }
 
 bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFeatures2& features) {
@@ -81,7 +103,6 @@
         VK_MAKE_VERSION(1, 1, 0),           // apiVersion
     };
 
-    std::vector<const char*> instanceExtensions;
     {
         GET_PROC(EnumerateInstanceExtensionProperties);
 
@@ -99,7 +120,7 @@
         bool hasKHRSurfaceExtension = false;
         bool hasKHRAndroidSurfaceExtension = false;
         for (uint32_t i = 0; i < extensionCount; ++i) {
-            instanceExtensions.push_back(extensions[i].extensionName);
+            mInstanceExtensions.push_back(extensions[i].extensionName);
             if (!strcmp(extensions[i].extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
                 hasKHRSurfaceExtension = true;
             }
@@ -120,8 +141,8 @@
         &app_info,                                 // pApplicationInfo
         0,                                         // enabledLayerNameCount
         nullptr,                                   // ppEnabledLayerNames
-        (uint32_t) instanceExtensions.size(),      // enabledExtensionNameCount
-        instanceExtensions.data(),                 // ppEnabledExtensionNames
+        (uint32_t) mInstanceExtensions.size(),     // enabledExtensionNameCount
+        mInstanceExtensions.data(),                // ppEnabledExtensionNames
     };
 
     GET_PROC(CreateInstance);
@@ -201,7 +222,6 @@
     // presentation with any native window. So just use the first one.
     mPresentQueueIndex = 0;
 
-    std::vector<const char*> deviceExtensions;
     {
         uint32_t extensionCount = 0;
         err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount,
@@ -220,7 +240,7 @@
         }
         bool hasKHRSwapchainExtension = false;
         for (uint32_t i = 0; i < extensionCount; ++i) {
-            deviceExtensions.push_back(extensions[i].extensionName);
+            mDeviceExtensions.push_back(extensions[i].extensionName);
             if (!strcmp(extensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
                 hasKHRSwapchainExtension = true;
             }
@@ -237,8 +257,8 @@
         }
         return vkGetInstanceProcAddr(instance, proc_name);
     };
-    grExtensions.init(getProc, mInstance, mPhysicalDevice, instanceExtensions.size(),
-            instanceExtensions.data(), deviceExtensions.size(), deviceExtensions.data());
+    grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
+            mInstanceExtensions.data(), mDeviceExtensions.size(), mDeviceExtensions.data());
 
     if (!grExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) {
         this->destroy();
@@ -308,8 +328,8 @@
         queueInfo,                               // pQueueCreateInfos
         0,                                       // layerCount
         nullptr,                                 // ppEnabledLayerNames
-        (uint32_t) deviceExtensions.size(),      // extensionCount
-        deviceExtensions.data(),                 // ppEnabledExtensionNames
+        (uint32_t) mDeviceExtensions.size(),     // extensionCount
+        mDeviceExtensions.data(),                // ppEnabledExtensionNames
         nullptr,                                 // ppEnabledFeatures
     };
 
@@ -351,36 +371,17 @@
     return true;
 }
 
-static void free_features_extensions_structs(const VkPhysicalDeviceFeatures2& features) {
-    // All Vulkan structs that could be part of the features chain will start with the
-    // structure type followed by the pNext pointer. We cast to the CommonVulkanHeader
-    // so we can get access to the pNext for the next struct.
-    struct CommonVulkanHeader {
-        VkStructureType sType;
-        void*           pNext;
-    };
-
-    void* pNext = features.pNext;
-    while (pNext) {
-        void* current = pNext;
-        pNext = static_cast<CommonVulkanHeader*>(current)->pNext;
-        free(current);
-    }
-}
-
 void VulkanManager::initialize() {
     if (mDevice != VK_NULL_HANDLE) {
         return;
     }
 
     GET_PROC(EnumerateInstanceVersion);
-    uint32_t instanceVersion = 0;
-    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&instanceVersion));
-    LOG_ALWAYS_FATAL_IF(instanceVersion < VK_MAKE_VERSION(1, 1, 0));
+    LOG_ALWAYS_FATAL_IF(mEnumerateInstanceVersion(&mInstanceVersion));
+    LOG_ALWAYS_FATAL_IF(mInstanceVersion < VK_MAKE_VERSION(1, 1, 0));
 
     GrVkExtensions extensions;
-    VkPhysicalDeviceFeatures2 features;
-    LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, features));
+    LOG_ALWAYS_FATAL_IF(!this->setupDevice(extensions, mPhysicalDeviceFeatures2));
 
     mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
 
@@ -397,9 +398,9 @@
     backendContext.fDevice = mDevice;
     backendContext.fQueue = mGraphicsQueue;
     backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
-    backendContext.fInstanceVersion = instanceVersion;
+    backendContext.fInstanceVersion = mInstanceVersion;
     backendContext.fVkExtensions = &extensions;
-    backendContext.fDeviceFeatures2 = &features;
+    backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
     backendContext.fGetProc = std::move(getProc);
 
     // create the command pool for the command buffers
@@ -433,13 +434,29 @@
     LOG_ALWAYS_FATAL_IF(!grContext.get());
     mRenderThread.setGrContext(grContext);
 
-    free_features_extensions_structs(features);
-
     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
         mSwapBehavior = SwapBehavior::BufferAge;
     }
 }
 
+VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
+    return VkFunctorInitParams{
+            .instance = mInstance,
+            .physical_device = mPhysicalDevice,
+            .device = mDevice,
+            .queue = mGraphicsQueue,
+            .graphics_queue_index = mGraphicsQueueIndex,
+            .instance_version = mInstanceVersion,
+            .enabled_instance_extension_names = mInstanceExtensions.data(),
+            .enabled_instance_extension_names_length =
+                    static_cast<uint32_t>(mInstanceExtensions.size()),
+            .enabled_device_extension_names = mDeviceExtensions.data(),
+            .enabled_device_extension_names_length =
+                    static_cast<uint32_t>(mDeviceExtensions.size()),
+            .device_features_2 = &mPhysicalDeviceFeatures2,
+    };
+}
+
 // Returns the next BackbufferInfo to use for the next draw. The function will make sure all
 // previous uses have finished before returning.
 VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurface* surface) {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 9eb942c..105ee09 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -132,6 +132,9 @@
     // Creates a fence that is signaled, when all the pending Vulkan commands are flushed.
     status_t createReleaseFence(sp<Fence>& nativeFence);
 
+    // Returned pointers are owned by VulkanManager.
+    VkFunctorInitParams getVkFunctorInitParams() const;
+
 private:
     friend class RenderThread;
 
@@ -234,6 +237,12 @@
 
     VkCommandBuffer mDummyCB = VK_NULL_HANDLE;
 
+    // Variables saved to populate VkFunctorInitParams.
+    uint32_t mInstanceVersion = 0u;
+    std::vector<const char*> mInstanceExtensions;
+    std::vector<const char*> mDeviceExtensions;
+    VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures2{};
+
     enum class SwapBehavior {
         Discard,
         BufferAge,
diff --git a/libs/services/include/android/os/DropBoxManager.h b/libs/services/include/android/os/DropBoxManager.h
index 75b26c6..0747243 100644
--- a/libs/services/include/android/os/DropBoxManager.h
+++ b/libs/services/include/android/os/DropBoxManager.h
@@ -62,7 +62,7 @@
     // file descriptor.
     Status addFile(const String16& tag, int fd, int flags);
 
-    class Entry : public virtual RefBase, public Parcelable {
+    class Entry : public Parcelable {
     public:
         Entry();
         virtual ~Entry();
@@ -89,9 +89,6 @@
         friend class DropBoxManager;
     };
 
-    // Get the next entry from the drop box after the specified time.
-    Status getNextEntry(const String16& tag, long msec, Entry* entry);
-
 private:
     enum {
         HAS_BYTE_ARRAY = 8
diff --git a/libs/services/src/os/DropBoxManager.cpp b/libs/services/src/os/DropBoxManager.cpp
index 8282518..681d5f7 100644
--- a/libs/services/src/os/DropBoxManager.cpp
+++ b/libs/services/src/os/DropBoxManager.cpp
@@ -228,15 +228,4 @@
     return service->add(entry);
 }
 
-Status
-DropBoxManager::getNextEntry(const String16& tag, long msec, Entry* entry)
-{
-    sp<IDropBoxManagerService> service = interface_cast<IDropBoxManagerService>(
-        defaultServiceManager()->getService(android::String16("dropbox")));
-    if (service == NULL) {
-        return Status::fromExceptionCode(Status::EX_NULL_POINTER, "can't find dropbox service");
-    }
-    return service->getNextEntry(tag, msec, android::String16("android"), entry);
-}
-
 }} // namespace android::os
diff --git a/media/Android.bp b/media/Android.bp
index d5da6f2..8ebc91a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,4 +1,21 @@
 java_library {
+    name: "media1",
+
+    srcs: [
+        ":media1-srcs",
+    ],
+
+    sdk_version: "system_current",
+}
+
+filegroup {
+    name: "media1-srcs",
+    srcs: [
+        "java/android/media/session/MediaSessionProviderService.java",
+    ],
+}
+
+java_library {
     // TODO: include media2.jar in the media apex and add it to the bootclasspath.
     name: "media2",
 
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 4f23cca..f5a6f86 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -736,8 +736,9 @@
          * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT},
          *     {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER},
          *     {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
-         *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION} or
-         *     {@link MediaRecorder.AudioSource#UNPROCESSED}
+         *     {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
+         *     {@link MediaRecorder.AudioSource#UNPROCESSED} or
+         *     {@link MediaRecorder.AudioSource#VOICE_PERFORMANCE}
          * @return the same Builder instance.
          */
         @SystemApi
@@ -749,6 +750,7 @@
                 case MediaRecorder.AudioSource.VOICE_RECOGNITION:
                 case MediaRecorder.AudioSource.VOICE_COMMUNICATION:
                 case MediaRecorder.AudioSource.UNPROCESSED:
+                case MediaRecorder.AudioSource.VOICE_PERFORMANCE:
                     mSource = preset;
                     break;
                 default:
@@ -760,7 +762,7 @@
         /**
          * @hide
          * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD,
-         * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK and VOICE_CALL.
+         * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK, VOICE_CALL and ECHO_REFERENCE.
          * @param preset
          * @return the same Builder instance.
          */
@@ -771,7 +773,8 @@
                     || (preset == MediaRecorder.AudioSource.RADIO_TUNER)
                     || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK)
                     || (preset == MediaRecorder.AudioSource.VOICE_UPLINK)
-                    || (preset == MediaRecorder.AudioSource.VOICE_CALL)) {
+                    || (preset == MediaRecorder.AudioSource.VOICE_CALL)
+                    || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)) {
                 mSource = preset;
             } else {
                 setCapturePreset(preset);
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 793aa27..5516086 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -816,7 +817,7 @@
      *
      * @return The audio frame size in bytes corresponding to the encoding and the channel mask.
      */
-    public int getFrameSizeInBytes() {
+    public @IntRange(from = 1) int getFrameSizeInBytes() {
         return mFrameSizeInBytes;
     }
 
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 33f81f1..92afe7e 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -61,7 +61,8 @@
  * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to
  * the total recording buffer size.
  */
-public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRecordingMonitorClient
+public class AudioRecord implements AudioRouting, MicrophoneDirection,
+        AudioRecordingMonitor, AudioRecordingMonitorClient
 {
     //---------------------------------------------------------
     // Constants
@@ -1657,7 +1658,6 @@
         return activeMicrophones;
     }
 
-
     //--------------------------------------------------------------------------
     // Implementation of AudioRecordingMonitor interface
     //--------------------
@@ -1707,6 +1707,33 @@
         return native_getPortId();
     }
 
+    //--------------------------------------------------------------------------
+    // MicrophoneDirection
+    //--------------------
+    /**
+     * Specifies the logical microphone (for processing).
+     *
+     * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
+     * @return retval OK if the call is successful, an error code otherwise.
+     * @hide
+     */
+    public int setMicrophoneDirection(int direction) {
+        return native_set_microphone_direction(direction);
+    }
+
+    /**
+     * Specifies the zoom factor (i.e. the field dimension) for the selected microphone
+     * (for processing). The selected microphone is determined by the use-case for the stream.
+     *
+     * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
+     * though 0 (no zoom) to 1 (maximum zoom).
+     * @return retval OK if the call is successful, an error code otherwise.
+     * @hide
+     */
+    public int setMicrophoneFieldDimension(float zoom) {
+        return native_set_microphone_field_dimension(zoom);
+    }
+
     //---------------------------------------------------------
     // Interface definitions
     //--------------------
@@ -1860,6 +1887,9 @@
 
     private native int native_getPortId();
 
+    private native int native_set_microphone_direction(int direction);
+    private native int native_set_microphone_field_dimension(float zoom);
+
     //---------------------------------------------------------
     // Utility methods
     //------------------
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index de76aef..52771e4 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -172,7 +172,8 @@
         MediaRecorder.AudioSource.CAMCORDER,
         MediaRecorder.AudioSource.VOICE_RECOGNITION,
         MediaRecorder.AudioSource.VOICE_COMMUNICATION,
-        MediaRecorder.AudioSource.UNPROCESSED
+        MediaRecorder.AudioSource.UNPROCESSED,
+        MediaRecorder.AudioSource.VOICE_PERFORMANCE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioSource {}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 45cde0f..de73649 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -541,6 +541,8 @@
     public static final int DEVICE_IN_BUS = DEVICE_BIT_IN | 0x100000;
     public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x1000000;
     public static final int DEVICE_IN_USB_HEADSET = DEVICE_BIT_IN | 0x2000000;
+    public static final int DEVICE_IN_BLUETOOTH_BLE = DEVICE_BIT_IN | 0x4000000;
+    public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000;
     @UnsupportedAppUsage
     public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
 
@@ -567,6 +569,8 @@
                                              DEVICE_IN_BUS |
                                              DEVICE_IN_PROXY |
                                              DEVICE_IN_USB_HEADSET |
+                                             DEVICE_IN_BLUETOOTH_BLE |
+                                             DEVICE_IN_ECHO_REFERENCE |
                                              DEVICE_IN_DEFAULT);
     public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
     public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
@@ -641,6 +645,8 @@
     public static final String DEVICE_IN_BUS_NAME = "bus";
     public static final String DEVICE_IN_PROXY_NAME = "proxy";
     public static final String DEVICE_IN_USB_HEADSET_NAME = "usb_headset";
+    public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble";
+    public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference";
 
     @UnsupportedAppUsage
     public static String getOutputDeviceName(int device)
@@ -757,6 +763,10 @@
             return DEVICE_IN_PROXY_NAME;
         case DEVICE_IN_USB_HEADSET:
             return DEVICE_IN_USB_HEADSET_NAME;
+        case DEVICE_IN_BLUETOOTH_BLE:
+            return DEVICE_IN_BLUETOOTH_BLE_NAME;
+        case DEVICE_IN_ECHO_REFERENCE:
+            return DEVICE_IN_ECHO_REFERENCE_NAME;
         case DEVICE_IN_DEFAULT:
         default:
             return Integer.toString(device);
diff --git a/media/java/android/media/IMediaSession2Service.aidl b/media/java/android/media/IMediaSession2Service.aidl
new file mode 100644
index 0000000..10ac1be
--- /dev/null
+++ b/media/java/android/media/IMediaSession2Service.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.Bundle;
+import android.media.Controller2Link;
+
+/**
+ * Interface from MediaController2 to MediaSession2Service.
+ * <p>
+ * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
+ * and holds calls from controller to make controller owner(s) frozen.
+ * @hide
+ */
+oneway interface IMediaSession2Service {
+    void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0;
+    // Next Id : 1
+}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index bc9500d..f756658 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1829,9 +1829,14 @@
 
         mBufferLock = new Object();
 
+        // save name used at creation
+        mNameAtCreation = nameIsType ? null : name;
+
         native_setup(name, nameIsType, encoder);
     }
 
+    private String mNameAtCreation;
+
     @Override
     protected void finalize() {
         native_finalize();
@@ -3317,12 +3322,36 @@
     private native void native_setAudioPresentation(int presentationId, int programId);
 
     /**
-     * Get the component name. If the codec was created by createDecoderByType
-     * or createEncoderByType, what component is chosen is not known beforehand.
+     * Retrieve the codec name.
+     *
+     * If the codec was created by createDecoderByType or createEncoderByType, what component is
+     * chosen is not known beforehand. This method returns the name of the codec that was
+     * selected by the platform.
+     *
+     * <strong>Note:</strong> Implementations may provide multiple aliases (codec
+     * names) for the same underlying codec, any of which can be used to instantiate the same
+     * underlying codec in {@link MediaCodec#createByCodecName}. This method returns the
+     * name used to create the codec in this case.
+     *
      * @throws IllegalStateException if in the Released state.
      */
     @NonNull
-    public native final String getName();
+    public final String getName() {
+        // get canonical name to handle exception
+        String canonicalName = getCanonicalName();
+        return mNameAtCreation != null ? mNameAtCreation : canonicalName;
+    }
+
+    /**
+     * Retrieve the underlying codec name.
+     *
+     * This method is similar to {@link #getName}, except that it returns the underlying component
+     * name even if an alias was used to create this MediaCodec object by name,
+     *
+     * @throws IllegalStateException if in the Released state.
+     */
+    @NonNull
+    public native final String getCanonicalName();
 
     /**
      *  Return Metrics data about the current codec instance.
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 10a1e3a..751d57b 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -32,8 +32,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.Vector;
 
 /**
  * Provides information about a given media codec available on the device. You can
@@ -61,15 +63,25 @@
  *
  */
 public final class MediaCodecInfo {
-    private boolean mIsEncoder;
+    private static final String TAG = "MediaCodecInfo";
+
+    private static final int FLAG_IS_ENCODER = (1 << 0);
+    private static final int FLAG_IS_VENDOR = (1 << 1);
+    private static final int FLAG_IS_SOFTWARE_ONLY = (1 << 2);
+    private static final int FLAG_IS_HARDWARE_ACCELERATED = (1 << 3);
+
+    private int mFlags;
     private String mName;
+    private String mCanonicalName;
     private Map<String, CodecCapabilities> mCaps;
 
     /* package private */ MediaCodecInfo(
-            String name, boolean isEncoder, CodecCapabilities[] caps) {
+            String name, String canonicalName, int flags, CodecCapabilities[] caps) {
         mName = name;
-        mIsEncoder = isEncoder;
+        mCanonicalName = canonicalName;
+        mFlags = flags;
         mCaps = new HashMap<String, CodecCapabilities>();
+
         for (CodecCapabilities c: caps) {
             mCaps.put(c.getMimeType(), c);
         }
@@ -77,16 +89,69 @@
 
     /**
      * Retrieve the codec name.
+     *
+     * <strong>Note:</strong> Implementations may provide multiple aliases (codec
+     * names) for the same underlying codec, any of which can be used to instantiate the same
+     * underlying codec in {@link MediaCodec#createByCodecName}.
+     *
+     * Applications targeting SDK < {@link android.os.Build.VERSION_CODES#Q}, cannot determine if
+     * the multiple codec names listed in MediaCodecList are in-fact for the same codec.
      */
+    @NonNull
     public final String getName() {
         return mName;
     }
 
     /**
+     * Retrieve the underlying codec name.
+     *
+     * Device implementations may provide multiple aliases (codec names) for the same underlying
+     * codec to maintain backward app compatibility. This method returns the name of the underlying
+     * codec name, which must not be another alias. For non-aliases this is always the name of the
+     * codec.
+     */
+    @NonNull
+    public final String getCanonicalName() {
+        return mCanonicalName;
+    }
+
+    /**
+     * Query if the codec is an alias for another underlying codec.
+     */
+    public final boolean isAlias() {
+        return !mName.equals(mCanonicalName);
+    }
+
+    /**
      * Query if the codec is an encoder.
      */
     public final boolean isEncoder() {
-        return mIsEncoder;
+        return (mFlags & FLAG_IS_ENCODER) != 0;
+    }
+
+    /**
+     * Query if the codec is provided by the Android platform (false) or the device manufacturer
+     * (true).
+     */
+    public final boolean isVendor() {
+        return (mFlags & FLAG_IS_VENDOR) != 0;
+    }
+
+    /**
+     * Query if the codec is software only. Software-only codecs are more secure as they run in
+     * a tighter security sandbox. On the other hand, software-only codecs do not provide any
+     * performance guarantees.
+     */
+    public final boolean isSoftwareOnly() {
+        return (mFlags & FLAG_IS_SOFTWARE_ONLY) != 0;
+    }
+
+    /**
+     * Query if the codec is hardware accelerated. This attribute is provided by the device
+     * manufacturer. Note that it cannot be tested for correctness.
+     */
+    public final boolean isHardwareAccelerated() {
+        return (mFlags & FLAG_IS_HARDWARE_ACCELERATED) != 0;
     }
 
     /**
@@ -163,7 +228,7 @@
         // such as B-frame support, arithmetic coding...
         public CodecProfileLevel[] profileLevels;  // NOTE this array is modifiable by user
 
-        // from OMX_COLOR_FORMATTYPE
+        // from MediaCodecConstants
         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
         public static final int COLOR_FormatMonochrome              = 1;
         /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */
@@ -344,7 +409,7 @@
         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
         public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
         // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
-        // In OMX this is called OMX_COLOR_FormatAndroidOpaque.
+        // Note: in OMX this is called OMX_COLOR_FormatAndroidOpaque.
         public static final int COLOR_FormatSurface                   = 0x7F000789;
 
         /**
@@ -435,8 +500,7 @@
         public static final int COLOR_QCOM_FormatYUV420SemiPlanar     = 0x7fa30c00;
 
         /**
-         * Defined in the OpenMAX IL specs, color format values are drawn from
-         * OMX_COLOR_FORMATTYPE.
+         * The color format for the media. This is one of the color constants defined in this class.
          */
         public int[] colorFormats; // NOTE this array is modifiable by user
 
@@ -462,6 +526,26 @@
         public static final String FEATURE_TunneledPlayback       = "tunneled-playback";
 
         /**
+         * If true, the timestamp of each output buffer is derived from the timestamp of the input
+         * buffer that produced the output. If false, the timestamp of each output buffer is
+         * derived from the timestamp of the first input buffer.
+         */
+        public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+
+        /**
+         * <b>decoder only</b>If true, the codec supports partial (including multiple) access units
+         * per input buffer.
+         */
+        public static final String FEATURE_FrameParsing = "frame-parsing";
+
+        /**
+         * If true, the codec supports multiple access units (for decoding, or to output for
+         * encoders). If false, the codec only supports single access units. Producing multiple
+         * access units for output is an optional feature.
+         */
+        public static final String FEATURE_MultipleFrames = "multiple-frames";
+
+        /**
          * <b>video decoder only</b>: codec supports queuing partial frames.
          */
         public static final String FEATURE_PartialFrame = "partial-frame";
@@ -497,10 +581,15 @@
             new Feature(FEATURE_SecurePlayback,   (1 << 1), false),
             new Feature(FEATURE_TunneledPlayback, (1 << 2), false),
             new Feature(FEATURE_PartialFrame,     (1 << 3), false),
+            new Feature(FEATURE_FrameParsing,     (1 << 4), false),
+            new Feature(FEATURE_MultipleFrames,   (1 << 5), false),
+            new Feature(FEATURE_DynamicTimestamp, (1 << 6), false),
         };
 
         private static final Feature[] encoderFeatures = {
             new Feature(FEATURE_IntraRefresh, (1 << 0), false),
+            new Feature(FEATURE_MultipleFrames, (1 << 1), false),
+            new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
         };
 
         /** @hide */
@@ -869,7 +958,7 @@
 
             CodecCapabilities ret = new CodecCapabilities(
                 new CodecProfileLevel[] { pl }, new int[0], true /* encoder */,
-                0 /* flags */, defaultFormat, new MediaFormat() /* info */);
+                defaultFormat, new MediaFormat() /* info */);
             if (ret.mError != 0) {
                 return null;
             }
@@ -878,10 +967,10 @@
 
         /* package private */ CodecCapabilities(
                 CodecProfileLevel[] profLevs, int[] colFmts,
-                boolean encoder, int flags,
+                boolean encoder,
                 Map<String, Object>defaultFormatMap,
                 Map<String, Object>capabilitiesMap) {
-            this(profLevs, colFmts, encoder, flags,
+            this(profLevs, colFmts, encoder,
                     new MediaFormat(defaultFormatMap),
                     new MediaFormat(capabilitiesMap));
         }
@@ -889,11 +978,11 @@
         private MediaFormat mCapabilitiesInfo;
 
         /* package private */ CodecCapabilities(
-                CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags,
+                CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder,
                 MediaFormat defaultFormat, MediaFormat info) {
             final Map<String, Object> map = info.getMap();
             colorFormats = colFmts;
-            mFlagsVerified = flags;
+            mFlagsVerified = 0; // TODO: remove as it is unused
             mDefaultFormat = defaultFormat;
             mCapabilitiesInfo = info;
             mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME);
@@ -1243,6 +1332,7 @@
         private Range<Rational> mBlockAspectRatioRange;
         private Range<Long> mBlocksPerSecondRange;
         private Map<Size, Range<Long>> mMeasuredFrameRates;
+        private Vector<PerformancePoint> mPerformancePoints;
         private Range<Integer> mFrameRateRange;
 
         private int mBlockWidth;
@@ -1524,6 +1614,158 @@
         }
 
         /**
+         * Video performance points are a set of standard performance points defined by pixel rate.
+         */
+        public static final class PerformancePoint {
+            /**
+             * Frame width in pixels.
+             */
+            public final int width;
+
+            /**
+             * Frame height in pixels.
+             */
+            public final int height;
+
+            /**
+             * Frame rate in frames per second.
+             */
+            public final int frameRate;
+
+            /* package private */
+            PerformancePoint(int width_, int height_, int frameRate_) {
+                width = width_;
+                height = height_;
+                frameRate = frameRate_;
+            }
+
+            /**
+             * Checks whether the performance point covers a media format.
+             *
+             * @param format Stream format considered
+             *
+             * @return {@code true} if the performance point covers the format.
+             */
+            public boolean covers(@NonNull MediaFormat format) {
+                // for simplicity, this code assumes a 16x16 block size.
+                long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16);
+                long mbps = macroBlocks * frameRate;
+
+                long formatMacroBlocks =
+                    (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16)
+                            * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16);
+                double formatMbps =
+                    Math.ceil(formatMacroBlocks
+                              * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue());
+                return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks
+                        && formatMbps <= mbps;
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (o instanceof PerformancePoint) {
+                    PerformancePoint other = (PerformancePoint)o;
+                    return ((long)width * height) == ((long)other.width * other.height)
+                            && frameRate == other.frameRate;
+                }
+                return false;
+            }
+
+            /** 480p 24fps */
+            public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24);
+            /** 576p 25fps */
+            public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25);
+            /** 480p 30fps */
+            public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30);
+            /** 480p 48fps */
+            public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48);
+            /** 576p 50fps */
+            public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50);
+            /** 480p 60fps */
+            public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60);
+
+            /** 720p 24fps */
+            public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24);
+            /** 720p 25fps */
+            public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25);
+            /** 720p 30fps */
+            public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30);
+            /** 720p 50fps */
+            public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50);
+            /** 720p 60fps */
+            public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60);
+            /** 720p 100fps */
+            public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100);
+            /** 720p 120fps */
+            public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120);
+            /** 720p 200fps */
+            public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200);
+            /** 720p 240fps */
+            public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240);
+
+            /** 1080p 24fps */
+            public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24);
+            /** 1080p 25fps */
+            public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25);
+            /** 1080p 30fps */
+            public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30);
+            /** 1080p 50fps */
+            public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50);
+            /** 1080p 60fps */
+            public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60);
+            /** 1080p 100fps */
+            public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100);
+            /** 1080p 120fps */
+            public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120);
+            /** 1080p 200fps */
+            public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200);
+            /** 1080p 240fps */
+            public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240);
+
+            /** 2160p 24fps */
+            public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24);
+            /** 2160p 25fps */
+            public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25);
+            /** 2160p 30fps */
+            public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30);
+            /** 2160p 50fps */
+            public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50);
+            /** 2160p 60fps */
+            public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60);
+            /** 2160p 100fps */
+            public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100);
+            /** 2160p 120fps */
+            public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120);
+            /** 2160p 200fps */
+            public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200);
+            /** 2160p 240fps */
+            public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240);
+        }
+
+        /**
+         * Returns the supported performance points. May return {@code null} if the codec did not
+         * publish any performance point information (e.g. the vendor codecs have not been updated
+         * to the latest android release). May return an empty list if the codec published that
+         * if does not guarantee any performance points.
+         * <p>
+         * This is a performance guarantee provided by the device manufacturer for hardware codecs
+         * based on hardware capabilities of the device.
+         * <p>
+         * The returned list is sorted first by decreasing number of pixels, then by decreasing
+         * width, and finally by decreasing frame rate.
+         * Performance points assume a single active codec. For use cases where multiple
+         * codecs are active, should use that highest pixel count, and add the frame rates of
+         * each individual codec.
+         */
+        @Nullable
+        public List<PerformancePoint> getSupportedPerformancePoints() {
+            if (mPerformancePoints == null) {
+                return null;
+            }
+            return new ArrayList<PerformancePoint>(mPerformancePoints);
+        }
+
+        /**
          * Returns whether a given video size ({@code width} and
          * {@code height}) and {@code frameRate} combination is supported.
          */
@@ -1659,6 +1901,50 @@
             mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
         }
 
+        private @Nullable Vector<PerformancePoint> getPerformancePoints(Map<String, Object> map) {
+            Vector<PerformancePoint> ret = new Vector<>();
+            final String prefix = "performance-point-";
+            Set<String> keys = map.keySet();
+            for (String key : keys) {
+                // looking for: performance-point-WIDTHxHEIGHT-range
+                if (!key.startsWith(prefix)) {
+                    continue;
+                }
+                String subKey = key.substring(prefix.length());
+                if (subKey.equals("none") && ret.size() == 0) {
+                    // This means that component knowingly did not publish performance points.
+                    // This is different from when the component forgot to publish performance
+                    // points.
+                    return ret;
+                }
+                String[] temp = key.split("-");
+                if (temp.length != 4) {
+                    continue;
+                }
+                String sizeStr = temp[2];
+                Size size = Utils.parseSize(sizeStr, null);
+                if (size == null || size.getWidth() * size.getHeight() <= 0) {
+                    continue;
+                }
+                Range<Long> range = Utils.parseLongRange(map.get(key), null);
+                if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
+                    continue;
+                }
+                ret.add(new PerformancePoint(
+                        size.getWidth(), size.getHeight(), range.getLower().intValue()));
+            }
+            // check if the component specified no performance point indication
+            if (ret.size() == 0) {
+                return null;
+            }
+
+            // sort reversed by area first, then by frame rate
+            ret.sort((a, b) -> (a.width * a.height != b.width * b.height ?
+                                    (b.width * b.height - a.width * a.height) :
+                                    (b.frameRate - a.frameRate)));
+            return ret;
+        }
+
         private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
             Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
             final String prefix = "measured-frame-rate-";
@@ -1770,6 +2056,7 @@
             blockRates =
                 Utils.parseLongRange(map.get("blocks-per-second-range"), null);
             mMeasuredFrameRates = getMeasuredFrameRates(map);
+            mPerformancePoints = getPerformancePoints(map);
             Pair<Range<Integer>, Range<Integer>> sizeRanges =
                 parseWidthHeightRanges(map.get("size-range"));
             if (sizeRanges != null) {
@@ -2879,7 +3166,9 @@
      * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field.
      */
     public static final class CodecProfileLevel {
-        // from OMX_VIDEO_AVCPROFILETYPE
+        // These constants were originally in-line with OMX values, but this
+        // correspondence is no longer maintained.
+
         public static final int AVCProfileBaseline = 0x01;
         public static final int AVCProfileMain     = 0x02;
         public static final int AVCProfileExtended = 0x04;
@@ -2890,7 +3179,6 @@
         public static final int AVCProfileConstrainedBaseline = 0x10000;
         public static final int AVCProfileConstrainedHigh     = 0x80000;
 
-        // from OMX_VIDEO_AVCLEVELTYPE
         public static final int AVCLevel1       = 0x01;
         public static final int AVCLevel1b      = 0x02;
         public static final int AVCLevel11      = 0x04;
@@ -2908,8 +3196,10 @@
         public static final int AVCLevel5       = 0x4000;
         public static final int AVCLevel51      = 0x8000;
         public static final int AVCLevel52      = 0x10000;
+        public static final int AVCLevel6       = 0x20000;
+        public static final int AVCLevel61      = 0x40000;
+        public static final int AVCLevel62      = 0x80000;
 
-        // from OMX_VIDEO_H263PROFILETYPE
         public static final int H263ProfileBaseline             = 0x01;
         public static final int H263ProfileH320Coding           = 0x02;
         public static final int H263ProfileBackwardCompatible   = 0x04;
@@ -2920,7 +3210,6 @@
         public static final int H263ProfileInterlace            = 0x80;
         public static final int H263ProfileHighLatency          = 0x100;
 
-        // from OMX_VIDEO_H263LEVELTYPE
         public static final int H263Level10      = 0x01;
         public static final int H263Level20      = 0x02;
         public static final int H263Level30      = 0x04;
@@ -2930,7 +3219,6 @@
         public static final int H263Level60      = 0x40;
         public static final int H263Level70      = 0x80;
 
-        // from OMX_VIDEO_MPEG4PROFILETYPE
         public static final int MPEG4ProfileSimple              = 0x01;
         public static final int MPEG4ProfileSimpleScalable      = 0x02;
         public static final int MPEG4ProfileCore                = 0x04;
@@ -2948,7 +3236,6 @@
         public static final int MPEG4ProfileAdvancedScalable    = 0x4000;
         public static final int MPEG4ProfileAdvancedSimple      = 0x8000;
 
-        // from OMX_VIDEO_MPEG4LEVELTYPE
         public static final int MPEG4Level0      = 0x01;
         public static final int MPEG4Level0b     = 0x02;
         public static final int MPEG4Level1      = 0x04;
@@ -2960,7 +3247,6 @@
         public static final int MPEG4Level5      = 0x80;
         public static final int MPEG4Level6      = 0x100;
 
-        // from OMX_VIDEO_MPEG2PROFILETYPE
         public static final int MPEG2ProfileSimple              = 0x00;
         public static final int MPEG2ProfileMain                = 0x01;
         public static final int MPEG2Profile422                 = 0x02;
@@ -2968,14 +3254,12 @@
         public static final int MPEG2ProfileSpatial             = 0x04;
         public static final int MPEG2ProfileHigh                = 0x05;
 
-        // from OMX_VIDEO_MPEG2LEVELTYPE
         public static final int MPEG2LevelLL     = 0x00;
         public static final int MPEG2LevelML     = 0x01;
         public static final int MPEG2LevelH14    = 0x02;
         public static final int MPEG2LevelHL     = 0x03;
         public static final int MPEG2LevelHP     = 0x04;
 
-        // from OMX_AUDIO_AACPROFILETYPE
         public static final int AACObjectMain       = 1;
         public static final int AACObjectLC         = 2;
         public static final int AACObjectSSR        = 3;
@@ -2990,16 +3274,13 @@
         /** xHE-AAC (includes USAC) */
         public static final int AACObjectXHE        = 42;
 
-        // from OMX_VIDEO_VP8LEVELTYPE
         public static final int VP8Level_Version0 = 0x01;
         public static final int VP8Level_Version1 = 0x02;
         public static final int VP8Level_Version2 = 0x04;
         public static final int VP8Level_Version3 = 0x08;
 
-        // from OMX_VIDEO_VP8PROFILETYPE
         public static final int VP8ProfileMain = 0x01;
 
-        // from OMX_VIDEO_VP9PROFILETYPE
         public static final int VP9Profile0 = 0x01;
         public static final int VP9Profile1 = 0x02;
         public static final int VP9Profile2 = 0x04;
@@ -3010,7 +3291,6 @@
         public static final int VP9Profile2HDR10Plus = 0x4000;
         public static final int VP9Profile3HDR10Plus = 0x8000;
 
-        // from OMX_VIDEO_VP9LEVELTYPE
         public static final int VP9Level1  = 0x1;
         public static final int VP9Level11 = 0x2;
         public static final int VP9Level2  = 0x4;
@@ -3026,14 +3306,12 @@
         public static final int VP9Level61 = 0x1000;
         public static final int VP9Level62 = 0x2000;
 
-        // from OMX_VIDEO_HEVCPROFILETYPE
         public static final int HEVCProfileMain        = 0x01;
         public static final int HEVCProfileMain10      = 0x02;
         public static final int HEVCProfileMainStill   = 0x04;
         public static final int HEVCProfileMain10HDR10 = 0x1000;
         public static final int HEVCProfileMain10HDR10Plus = 0x2000;
 
-        // from OMX_VIDEO_HEVCLEVELTYPE
         public static final int HEVCMainTierLevel1  = 0x1;
         public static final int HEVCHighTierLevel1  = 0x2;
         public static final int HEVCMainTierLevel2  = 0x4;
@@ -3067,7 +3345,6 @@
             HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 |
             HEVCHighTierLevel62;
 
-        // from OMX_VIDEO_DOLBYVISIONPROFILETYPE
         public static final int DolbyVisionProfileDvavPer = 0x1;
         public static final int DolbyVisionProfileDvavPen = 0x2;
         public static final int DolbyVisionProfileDvheDer = 0x4;
@@ -3079,7 +3356,6 @@
         public static final int DolbyVisionProfileDvheSt = 0x100;
         public static final int DolbyVisionProfileDvavSe = 0x200;
 
-        // from OMX_VIDEO_DOLBYVISIONLEVELTYPE
         public static final int DolbyVisionLevelHd24    = 0x1;
         public static final int DolbyVisionLevelHd30    = 0x2;
         public static final int DolbyVisionLevelFhd24   = 0x4;
@@ -3090,17 +3366,44 @@
         public static final int DolbyVisionLevelUhd48   = 0x80;
         public static final int DolbyVisionLevelUhd60   = 0x100;
 
+        public static final int AV1Profile0     = 0x1;
+        public static final int AV1Profile1     = 0x2;
+        public static final int AV1Profile2     = 0x4;
+
+        public static final int AV1Level2       = 0x1;
+        public static final int AV1Level21      = 0x2;
+        public static final int AV1Level22      = 0x4;
+        public static final int AV1Level23      = 0x8;
+        public static final int AV1Level3       = 0x10;
+        public static final int AV1Level31      = 0x20;
+        public static final int AV1Level32      = 0x40;
+        public static final int AV1Level33      = 0x80;
+        public static final int AV1Level4       = 0x100;
+        public static final int AV1Level41      = 0x200;
+        public static final int AV1Level42      = 0x400;
+        public static final int AV1Level43      = 0x800;
+        public static final int AV1Level5       = 0x1000;
+        public static final int AV1Level51      = 0x2000;
+        public static final int AV1Level52      = 0x4000;
+        public static final int AV1Level53      = 0x8000;
+        public static final int AV1Level6       = 0x10000;
+        public static final int AV1Level61      = 0x20000;
+        public static final int AV1Level62      = 0x40000;
+        public static final int AV1Level63      = 0x80000;
+        public static final int AV1Level7       = 0x100000;
+        public static final int AV1Level71      = 0x200000;
+        public static final int AV1Level72      = 0x400000;
+        public static final int AV1Level73      = 0x800000;
+
         /**
-         * Defined in the OpenMAX IL specs, depending on the type of media
-         * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
-         * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE.
+         * The profile of the media content. Depending on the type of media this can be
+         * one of the profile values defined in this class.
          */
         public int profile;
 
         /**
-         * Defined in the OpenMAX IL specs, depending on the type of media
-         * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE
-         * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE.
+         * The level of the media content. Depending on the type of media this can be
+         * one of the level values defined in this class.
          *
          * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may
          * not advertise a profile level support. For those VP9 decoders, please use
@@ -3157,7 +3460,7 @@
         }
 
         return new MediaCodecInfo(
-                mName, mIsEncoder,
+                mName, mCanonicalName, mFlags,
                 caps.toArray(new CodecCapabilities[caps.size()]));
     }
 }
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 2e47865..a460954 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -111,12 +111,14 @@
             caps[typeIx++] = getCodecCapabilities(index, type);
         }
         return new MediaCodecInfo(
-                getCodecName(index), isEncoder(index), caps);
+                getCodecName(index), getCanonicalName(index), getAttributes(index), caps);
     }
 
     /* package private */ static native final String getCodecName(int index);
 
-    /* package private */ static native final boolean isEncoder(int index);
+    /* package private */ static native final String getCanonicalName(int index);
+
+    /* package private */ static native final int getAttributes(int index);
 
     /* package private */ static native final String[] getSupportedTypes(int index);
 
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 774ea18..165ea41 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -26,12 +26,16 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -63,6 +67,7 @@
     private final Executor mCallbackExecutor;
     private final Controller2Link mControllerStub;
     private final Handler mResultHandler;
+    private final SessionServiceConnection mServiceConnection;
 
     private final Object mLock = new Object();
     //@GuardedBy("mLock")
@@ -118,16 +123,25 @@
         mPendingCommands = new ArrayMap<>();
         mRequestedCommandSeqNumbers = new ArraySet<>();
 
+        boolean connectRequested;
         if (token.getType() == TYPE_SESSION) {
-            connectToSession();
+            mServiceConnection = null;
+            connectRequested = requestConnectToSession();
         } else {
-            // TODO: Handle connect to session service.
+            mServiceConnection = new SessionServiceConnection();
+            connectRequested = requestConnectToService();
+        }
+        if (!connectRequested) {
+            close();
         }
     }
 
     @Override
     public void close() {
         synchronized (mLock) {
+            if (mServiceConnection != null) {
+                mContext.unbindService(mServiceConnection);
+            }
             if (mSessionBinder != null) {
                 try {
                     mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
@@ -299,18 +313,55 @@
         }
     }
 
-    private void connectToSession() {
-        Session2Link sessionBinder = mSessionToken.getSessionLink();
+    private Bundle createConnectionRequest() {
         Bundle connectionRequest = new Bundle();
         connectionRequest.putString(KEY_PACKAGE_NAME, mContext.getPackageName());
         connectionRequest.putInt(KEY_PID, Process.myPid());
+        return connectionRequest;
+    }
 
+    private boolean requestConnectToSession() {
+        Session2Link sessionBinder = mSessionToken.getSessionLink();
+        Bundle connectionRequest = createConnectionRequest();
         try {
             sessionBinder.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
         } catch (RuntimeException e) {
-            Log.w(TAG, "Failed to call connection request. Framework will retry"
-                    + " automatically");
+            Log.w(TAG, "Failed to call connection request", e);
+            return false;
         }
+        return true;
+    }
+
+    private boolean requestConnectToService() {
+        // Service. Needs to get fresh binder whenever connection is needed.
+        final Intent intent = new Intent(MediaSession2Service.SERVICE_INTERFACE);
+        intent.setClassName(mSessionToken.getPackageName(), mSessionToken.getServiceName());
+
+        // Use bindService() instead of startForegroundService() to start session service for three
+        // reasons.
+        // 1. Prevent session service owner's stopSelf() from destroying service.
+        //    With the startForegroundService(), service's call of stopSelf() will trigger immediate
+        //    onDestroy() calls on the main thread even when onConnect() is running in another
+        //    thread.
+        // 2. Minimize APIs for developers to take care about.
+        //    With bindService(), developers only need to take care about Service.onBind()
+        //    but Service.onStartCommand() should be also taken care about with the
+        //    startForegroundService().
+        // 3. Future support for UI-less playback
+        //    If a service wants to keep running, it should be either foreground service or
+        //    bound service. But there had been request for the feature for system apps
+        //    and using bindService() will be better fit with it.
+        synchronized (mLock) {
+            boolean result = mContext.bindService(
+                    intent, mServiceConnection, Context.BIND_AUTO_CREATE);
+            if (!result) {
+                Log.w(TAG, "bind to " + mSessionToken + " failed");
+                return false;
+            } else if (DEBUG) {
+                Log.d(TAG, "bind to " + mSessionToken + " succeeded");
+            }
+        }
+        return true;
     }
 
     /**
@@ -367,4 +418,59 @@
         public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token,
                 @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
     }
+
+    // This will be called on the main thread.
+    private class SessionServiceConnection implements ServiceConnection {
+        SessionServiceConnection() {
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            // Note that it's always main-thread.
+            boolean connectRequested = false;
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "onServiceConnected " + name + " " + this);
+                }
+                // Sanity check
+                if (!mSessionToken.getPackageName().equals(name.getPackageName())) {
+                    Log.wtf(TAG, "Expected connection to " + mSessionToken.getPackageName()
+                            + " but is connected to " + name);
+                    return;
+                }
+                IMediaSession2Service iService = IMediaSession2Service.Stub.asInterface(service);
+                if (iService == null) {
+                    Log.wtf(TAG, "Service interface is missing.");
+                    return;
+                }
+                Bundle connectionRequest = createConnectionRequest();
+                iService.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
+                connectRequested = true;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Service " + name + " has died prematurely", e);
+            } finally {
+                if (!connectRequested) {
+                    close();
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            // Temporal lose of the binding because of the service crash. System will automatically
+            // rebind, so just no-op.
+            if (DEBUG) {
+                Log.w(TAG, "Session service " + name + " is disconnected.");
+            }
+            close();
+        }
+
+        @Override
+        public void onBindingDied(ComponentName name) {
+            // Permanent lose of the binding because of the service package update or removed.
+            // This SessionServiceRecord will be removed accordingly, but forget session binder here
+            // for sure.
+            close();
+        }
+    }
 }
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 594a224..c82b5f6 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -124,6 +124,7 @@
 public final class MediaFormat {
     public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
     public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+    public static final String MIMETYPE_VIDEO_AV1 = "video/av01";
     public static final String MIMETYPE_VIDEO_AVC = "video/avc";
     public static final String MIMETYPE_VIDEO_HEVC = "video/hevc";
     public static final String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index a836f4a..aa79c41 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -776,7 +776,7 @@
                 }
                 boolean hasError = false;
                 for (DataSourceDesc dsd : dsds) {
-                    if (dsd != null) {
+                    if (dsd == null) {
                         hasError = true;
                         continue;
                     }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 25b1df2..1304afe 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -302,6 +302,34 @@
          *  {@link #DEFAULT} otherwise. */
         public static final int UNPROCESSED = 9;
 
+
+        /**
+         * Source for capturing audio meant to be processed in real time and played back for live
+         * performance (e.g karaoke).
+         * <p>
+         * The capture path will minimize latency and coupling with
+         * playback path.
+         * </p>
+         */
+        public static final int VOICE_PERFORMANCE = 10;
+
+        /**
+         * Source for an echo canceller to capture the reference signal to be cancelled.
+         * <p>
+         * The echo reference signal will be captured as close as possible to the DAC in order
+         * to include all post processing applied to the playback path.
+         * </p><p>
+         * Capturing the echo reference requires the
+         * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
+         * This permission is reserved for use by system components and is not available to
+         * third-party applications.
+         * </p>
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)
+        public static final int ECHO_REFERENCE = 1997;
+
         /**
          * Audio source for capturing broadcast radio tuner output.
          * @hide
@@ -343,6 +371,7 @@
         case AudioSource.VOICE_COMMUNICATION:
         //case REMOTE_SUBMIX:  considered "system" as it requires system permissions
         case AudioSource.UNPROCESSED:
+        case AudioSource.VOICE_PERFORMANCE:
             return false;
         default:
             return true;
@@ -372,6 +401,10 @@
             return "REMOTE_SUBMIX";
         case AudioSource.UNPROCESSED:
             return "UNPROCESSED";
+        case AudioSource.ECHO_REFERENCE:
+            return "ECHO_REFERENCE";
+        case AudioSource.VOICE_PERFORMANCE:
+            return "VOICE_PERFORMANCE";
         case AudioSource.RADIO_TUNER:
             return "RADIO_TUNER";
         case AudioSource.HOTWORD:
@@ -524,7 +557,7 @@
      * @see android.media.MediaRecorder.AudioSource
      */
     public static final int getAudioSourceMax() {
-        return AudioSource.UNPROCESSED;
+        return AudioSource.VOICE_PERFORMANCE;
     }
 
     /**
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index e008adf..04999ca 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -31,7 +31,6 @@
 import android.content.Intent;
 import android.media.session.MediaSessionManager;
 import android.media.session.MediaSessionManager.RemoteUserInfo;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Process;
@@ -41,7 +40,6 @@
 import android.util.Log;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -117,15 +115,19 @@
     @Override
     public void close() {
         try {
+            List<ControllerInfo> controllerInfos;
+            synchronized (mLock) {
+                if (mClosed) {
+                    return;
+                }
+                mClosed = true;
+                controllerInfos = getConnectedControllers();
+                mConnectedControllers.clear();
+                mCallback.onSessionClosed(this);
+            }
             synchronized (MediaSession2.class) {
                 SESSION_ID_LIST.remove(mSessionId);
             }
-            Collection<ControllerInfo> controllerInfos;
-            synchronized (mLock) {
-                controllerInfos = mConnectedControllers.values();
-                mConnectedControllers.clear();
-                mClosed = true;
-            }
             for (ControllerInfo info : controllerInfos) {
                 info.notifyDisconnected();
             }
@@ -160,10 +162,7 @@
         if (command == null) {
             throw new IllegalArgumentException("command shouldn't be null");
         }
-        Collection<ControllerInfo> controllerInfos;
-        synchronized (mLock) {
-            controllerInfos = mConnectedControllers.values();
-        }
+        List<ControllerInfo> controllerInfos = getConnectedControllers();
         for (ControllerInfo controller : controllerInfos) {
             controller.sendSessionCommand(command, args, null);
         }
@@ -222,23 +221,26 @@
         }
     }
 
-    // Called by Session2Link.onConnect
-    void onConnect(final Controller2Link controller, int seq, Bundle connectionRequest) {
-        if (controller == null || connectionRequest == null) {
-            return;
+    SessionCallback getCallback() {
+        return mCallback;
+    }
+
+    // Called by Session2Link.onConnect and MediaSession2Service.MediaSession2ServiceStub.connect
+    void onConnect(final Controller2Link controller, int callingPid, int callingUid, int seq,
+            Bundle connectionRequest) {
+        if (callingPid == 0) {
+            // The pid here is from Binder.getCallingPid(), which can be 0 for an oneway call from
+            // the remote process. If it's the case, use PID from the connectionRequest.
+            callingPid = connectionRequest.getInt(KEY_PID);
         }
-        final int uid = Binder.getCallingUid();
-        final int callingPid = Binder.getCallingPid();
-        final long token = Binder.clearCallingIdentity();
-        // Binder.getCallingPid() can be 0 for an oneway call from the remote process.
-        // If it's the case, use PID from the ConnectionRequest.
-        final int pid = (callingPid != 0) ? callingPid : connectionRequest.getInt(KEY_PID);
-        final String pkg = connectionRequest.getString(KEY_PACKAGE_NAME);
-        try {
-            RemoteUserInfo remoteUserInfo = new RemoteUserInfo(pkg, pid, uid);
-            final ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo,
-                    mSessionManager.isTrustedForMediaControl(remoteUserInfo), controller);
-            mCallbackExecutor.execute(() -> {
+        String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
+
+        RemoteUserInfo remoteUserInfo = new RemoteUserInfo(callingPkg, callingPid, callingUid);
+        final ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo,
+                mSessionManager.isTrustedForMediaControl(remoteUserInfo), controller);
+        mCallbackExecutor.execute(() -> {
+            boolean connected = false;
+            try {
                 if (isClosed()) {
                     return;
                 }
@@ -247,77 +249,71 @@
                 // Don't reject connection for the request from trusted app.
                 // Otherwise server will fail to retrieve session's information to dispatch
                 // media keys to.
-                boolean accept =
-                        controllerInfo.mAllowedCommands != null || controllerInfo.isTrusted();
-                if (accept) {
-                    if (controllerInfo.mAllowedCommands == null) {
-                        // For trusted apps, send non-null allowed commands to keep
-                        // connection.
-                        controllerInfo.mAllowedCommands =
-                                new Session2CommandGroup.Builder().build();
+                if (controllerInfo.mAllowedCommands == null && !controllerInfo.isTrusted()) {
+                    return;
+                }
+                if (controllerInfo.mAllowedCommands == null) {
+                    // For trusted apps, send non-null allowed commands to keep
+                    // connection.
+                    controllerInfo.mAllowedCommands =
+                            new Session2CommandGroup.Builder().build();
+                }
+                if (DEBUG) {
+                    Log.d(TAG, "Accepting connection: " + controllerInfo);
+                }
+                synchronized (mLock) {
+                    if (mConnectedControllers.containsKey(controller)) {
+                        Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
+                                + " request multiple times");
                     }
+                    mConnectedControllers.put(controller, controllerInfo);
+                }
+                // If connection is accepted, notify the current state to the controller.
+                // It's needed because we cannot call synchronous calls between
+                // session/controller.
+                Bundle connectionResult = new Bundle();
+                connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
+                connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
+                        controllerInfo.mAllowedCommands);
+
+                // Double check if session is still there, because close() can be called in
+                // another thread.
+                if (isClosed()) {
+                    return;
+                }
+                controllerInfo.notifyConnected(connectionResult);
+                connected = true;
+            } finally {
+                if (!connected) {
                     if (DEBUG) {
-                        Log.d(TAG, "Accepting connection: " + controllerInfo);
+                        Log.d(TAG, "Rejecting connection or notifying that session is closed"
+                                + ", controllerInfo=" + controllerInfo);
                     }
                     synchronized (mLock) {
-                        if (mConnectedControllers.containsKey(controller)) {
-                            Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
-                                    + " request multiple times");
-                        }
-                        mConnectedControllers.put(controller, controllerInfo);
-                    }
-                    // If connection is accepted, notify the current state to the controller.
-                    // It's needed because we cannot call synchronous calls between
-                    // session/controller.
-                    Bundle connectionResult = new Bundle();
-                    connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
-                    connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
-                            controllerInfo.mAllowedCommands);
-
-                    // Double check if session is still there, because close() can be called in
-                    // another thread.
-                    if (isClosed()) {
-                        return;
-                    }
-                    controllerInfo.notifyConnected(connectionResult);
-                } else {
-                    if (DEBUG) {
-                        Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo);
+                        mConnectedControllers.remove(controller);
                     }
                     controllerInfo.notifyDisconnected();
                 }
-            });
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+            }
+        });
     }
 
     // Called by Session2Link.onDisconnect
-    void onDisconnect(final Controller2Link controller, int seq) {
-        if (controller == null) {
-            return;
-        }
+    void onDisconnect(@NonNull final Controller2Link controller, int seq) {
         final ControllerInfo controllerInfo;
         synchronized (mLock) {
-            controllerInfo = mConnectedControllers.get(controller);
+            controllerInfo = mConnectedControllers.remove(controller);
         }
         if (controllerInfo == null) {
             return;
         }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            mCallbackExecutor.execute(() -> {
-                mCallback.onDisconnected(MediaSession2.this, controllerInfo);
-            });
-            mConnectedControllers.remove(controller);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+        mCallbackExecutor.execute(() -> {
+            mCallback.onDisconnected(MediaSession2.this, controllerInfo);
+        });
     }
 
     // Called by Session2Link.onSessionCommand
-    void onSessionCommand(final Controller2Link controller, final int seq,
+    void onSessionCommand(@NonNull final Controller2Link controller, final int seq,
             final Session2Command command, final Bundle args,
             @Nullable ResultReceiver resultReceiver) {
         if (controller == null) {
@@ -332,34 +328,28 @@
         }
 
         // TODO: check allowed commands.
-        final long token = Binder.clearCallingIdentity();
-        try {
-            synchronized (mLock) {
-                controllerInfo.addRequestedCommandSeqNumber(seq);
-            }
-
-            mCallbackExecutor.execute(() -> {
-                if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
-                    resultReceiver.send(RESULT_INFO_SKIPPED, null);
-                    return;
-                }
-                Session2Command.Result result = mCallback.onSessionCommand(
-                        MediaSession2.this, controllerInfo, command, args);
-                if (resultReceiver != null) {
-                    if (result == null) {
-                        throw new RuntimeException("onSessionCommand shouldn't return null");
-                    } else {
-                        resultReceiver.send(result.getResultCode(), result.getResultData());
-                    }
-                }
-            });
-        } finally {
-            Binder.restoreCallingIdentity(token);
+        synchronized (mLock) {
+            controllerInfo.addRequestedCommandSeqNumber(seq);
         }
+        mCallbackExecutor.execute(() -> {
+            if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
+                resultReceiver.send(RESULT_INFO_SKIPPED, null);
+                return;
+            }
+            Session2Command.Result result = mCallback.onSessionCommand(
+                    MediaSession2.this, controllerInfo, command, args);
+            if (resultReceiver != null) {
+                if (result == null) {
+                    throw new RuntimeException("onSessionCommand shouldn't return null");
+                } else {
+                    resultReceiver.send(result.getResultCode(), result.getResultData());
+                }
+            }
+        });
     }
 
     // Called by Session2Link.onCancelCommand
-    void onCancelCommand(final Controller2Link controller, final int seq) {
+    void onCancelCommand(@NonNull final Controller2Link controller, final int seq) {
         final ControllerInfo controllerInfo;
         synchronized (mLock) {
             controllerInfo = mConnectedControllers.get(controller);
@@ -367,13 +357,15 @@
         if (controllerInfo == null) {
             return;
         }
+        controllerInfo.removeRequestedCommandSeqNumber(seq);
+    }
 
-        final long token = Binder.clearCallingIdentity();
-        try {
-            controllerInfo.removeRequestedCommandSeqNumber(seq);
-        } finally {
-            Binder.restoreCallingIdentity(token);
+    private List<ControllerInfo> getConnectedControllers() {
+        List<ControllerInfo> controllers = new ArrayList<>();
+        synchronized (mLock) {
+            controllers.addAll(mConnectedControllers.values());
         }
+        return controllers;
     }
 
     /**
@@ -660,6 +652,8 @@
      * This API is not generally intended for third party application developers.
      */
     public abstract static class SessionCallback {
+        ForegroundServiceEventCallback mForegroundServiceEventCallback;
+
         /**
          * Called when a controller is created for this session. Return allowed commands for
          * controller. By default it returns {@code null}.
@@ -716,5 +710,19 @@
         public void onCommandResult(@NonNull MediaSession2 session,
                 @NonNull ControllerInfo controller, @NonNull Object token,
                 @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
+
+        final void onSessionClosed(MediaSession2 session) {
+            if (mForegroundServiceEventCallback != null) {
+                mForegroundServiceEventCallback.onSessionClosed(session);
+            }
+        }
+
+        void setForegroundServiceEventCallback(ForegroundServiceEventCallback callback) {
+            mForegroundServiceEventCallback = callback;
+        }
+
+        abstract static class ForegroundServiceEventCallback {
+            public void onSessionClosed(MediaSession2 session) {}
+        }
     }
 }
diff --git a/media/java/android/media/MediaSession2Service.java b/media/java/android/media/MediaSession2Service.java
new file mode 100644
index 0000000..8fb00fe
--- /dev/null
+++ b/media/java/android/media/MediaSession2Service.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Service containing {@link MediaSession2}.
+ * <p>
+ * This API is not generally intended for third party application developers.
+ * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
+ * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a>
+ * for consistent behavior across all devices.
+ * @hide
+ */
+// TODO: Unhide
+// TODO: Add onUpdateNotification(), and calls it to get Notification for startForegroundService()
+//       when a session's player state becomes playing.
+public abstract class MediaSession2Service extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
+
+    private static final String TAG = "MediaSession2Service";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private Map<String, MediaSession2> mSessions = new ArrayMap<>();
+
+    private MediaSession2ServiceStub mStub;
+
+    /**
+     * Called by the system when the service is first created. Do not call this method directly.
+     * <p>
+     * Override this method if you need your own initialization. Derived classes MUST call through
+     * to the super class's implementation of this method.
+     */
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mStub = new MediaSession2ServiceStub(this);
+    }
+
+    @CallSuper
+    @Override
+    @Nullable
+    public IBinder onBind(@NonNull Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mStub;
+        }
+        return null;
+    }
+
+    @CallSuper
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        // TODO: Dispatch media key events to the primary session.
+        return START_STICKY;
+    }
+
+    /**
+     * Called by the system to notify that it is no longer used and is being removed. Do not call
+     * this method directly.
+     * <p>
+     * Override this method if you need your own clean up. Derived classes MUST call through
+     * to the super class's implementation of this method.
+     */
+    @CallSuper
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        synchronized (mLock) {
+            for (MediaSession2 session : mSessions.values()) {
+                session.getCallback().setForegroundServiceEventCallback(null);
+            }
+            mSessions.clear();
+        }
+        mStub.close();
+    }
+
+    /**
+     * Called when a {@link MediaController2} is created with the this service's
+     * {@link Session2Token}. Return the primary session for telling the controller which session to
+     * connect.
+     * <p>
+     * Primary session is the highest priority session that this service manages. Here are some
+     * recommendations of the primary session.
+     * <ol>
+     * <li>When there's no {@link MediaSession2}, create and return a new session. Resume the
+     * playback that the app has the lastly played with the new session. The behavior is what
+     * framework expects when the framework sends key events to the service.</li>
+     * <li>When there's multiple {@link MediaSession2}s, pick the session that has the lastly
+     * started the playback. This is the same way as the framework prioritize sessions to receive
+     * media key events.</li>
+     * </ol>
+     * <p>
+     * Session returned here will be added to this service automatically. You don't need to call
+     * {@link #addSession(MediaSession2)} for that.
+     * <p>
+     * Session service will accept or reject the connection with the
+     * {@link MediaSession2.SessionCallback} in the session returned here.
+     * <p>
+     * This method is always called on the main thread.
+     *
+     * @return a new session
+     * @see MediaSession2.Builder
+     * @see #getSessions()
+     */
+    @NonNull
+    public abstract MediaSession2 onGetPrimarySession();
+
+    /**
+     * Adds a session to this service.
+     * <p>
+     * Added session will be removed automatically when it's closed, or removed when
+     * {@link #removeSession} is called.
+     *
+     * @param session a session to be added.
+     * @see #removeSession(MediaSession2)
+     */
+    public final void addSession(@NonNull MediaSession2 session) {
+        if (session == null) {
+            throw new IllegalArgumentException("session shouldn't be null");
+        }
+        if (session.isClosed()) {
+            throw new IllegalArgumentException("session is already closed");
+        }
+        synchronized (mLock) {
+            MediaSession2 previousSession = mSessions.get(session.getSessionId());
+            if (previousSession != session) {
+                if (previousSession != null) {
+                    Log.w(TAG, "Session ID should be unique, ID=" + session.getSessionId()
+                            + ", previous=" + previousSession + ", session=" + session);
+                }
+                return;
+            }
+            mSessions.put(session.getSessionId(), session);
+            session.getCallback().setForegroundServiceEventCallback(
+                    new MediaSession2.SessionCallback.ForegroundServiceEventCallback() {
+                        @Override
+                        public void onSessionClosed(MediaSession2 session) {
+                            removeSession(session);
+                        }
+                    });
+        }
+    }
+
+    /**
+     * Removes a session from this service.
+     *
+     * @param session a session to be removed.
+     * @see #addSession(MediaSession2)
+     */
+    public final void removeSession(@NonNull MediaSession2 session) {
+        if (session == null) {
+            throw new IllegalArgumentException("session shouldn't be null");
+        }
+        synchronized (mLock) {
+            mSessions.remove(session.getSessionId());
+        }
+    }
+
+    /**
+     * Gets the list of {@link MediaSession2}s that you've added to this service.
+     *
+     * @return sessions
+     */
+    public final @NonNull List<MediaSession2> getSessions() {
+        List<MediaSession2> list = new ArrayList<>();
+        synchronized (mLock) {
+            list.addAll(mSessions.values());
+        }
+        return list;
+    }
+
+    private static final class MediaSession2ServiceStub extends IMediaSession2Service.Stub
+            implements AutoCloseable {
+        final WeakReference<MediaSession2Service> mService;
+        final Handler mHandler;
+
+        MediaSession2ServiceStub(MediaSession2Service service) {
+            mService = new WeakReference<>(service);
+            mHandler = new Handler(service.getMainLooper());
+        }
+
+        @Override
+        public void connect(Controller2Link caller, int seq, Bundle connectionRequest) {
+            if (mService.get() == null) {
+                if (DEBUG) {
+                    Log.d(TAG, "Service is already destroyed");
+                }
+                return;
+            }
+            if (caller == null || connectionRequest == null) {
+                if (DEBUG) {
+                    Log.d(TAG, "Ignoring calls with illegal arguments, caller=" + caller
+                            + ", connectionRequest=" + connectionRequest);
+                }
+                return;
+            }
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mHandler.post(() -> {
+                    boolean shouldNotifyDisconnected = true;
+                    try {
+                        final MediaSession2Service service = mService.get();
+                        if (service == null) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Service isn't available");
+                            }
+                            return;
+                        }
+                        if (DEBUG) {
+                            Log.d(TAG, "Handling incoming connection request from the"
+                                    + " controller, controller=" + caller + ", uid=" + uid);
+                        }
+                        final MediaSession2 session;
+                        session = service.onGetPrimarySession();
+                        service.addSession(session);
+                        shouldNotifyDisconnected = false;
+                        session.onConnect(caller, pid, uid, seq, connectionRequest);
+                    } catch (Exception e) {
+                        // Don't propagate exception in service to the controller.
+                        Log.w(TAG, "Failed to add a session to session service", e);
+                    } finally {
+                        // Trick to call onDisconnected() in one place.
+                        if (shouldNotifyDisconnected) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Service has destroyed prematurely."
+                                        + " Rejecting connection");
+                            }
+                            try {
+                                caller.notifyDisconnected(0);
+                            } catch (RuntimeException e) {
+                                // Controller may be died prematurely.
+                                // Not an issue because we'll ignore it anyway.
+                            }
+                        }
+                    }
+                });
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void close() {
+            mHandler.removeCallbacksAndMessages(null);
+            mService.clear();
+        }
+    }
+}
diff --git a/media/java/android/media/MicrophoneDirection.java b/media/java/android/media/MicrophoneDirection.java
new file mode 100644
index 0000000..99201c0
--- /dev/null
+++ b/media/java/android/media/MicrophoneDirection.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * @hide
+ */
+public interface MicrophoneDirection {
+    /**
+     * @hide
+     */
+    int MIC_DIRECTION_UNSPECIFIED = 0;
+
+    /**
+     * @hide
+     */
+    int MIC_DIRECTION_FRONT = 1;
+
+    /**
+     * @hide
+     */
+    int MIC_DIRECTION_BACK = 2;
+
+    /**
+     * @hide
+     */
+    int MIC_DIRECTION_EXTERNAL = 3;
+
+    /**
+     * Specifies the logical microphone (for processing).
+     *
+     * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*)
+     * @return retval OK if the call is successful, an error code otherwise.
+     * @hide
+     */
+    int setMicrophoneDirection(int direction);
+
+    /**
+     * Specifies the zoom factor (i.e. the field dimension) for the selected microphone
+     * (for processing). The selected microphone is determined by the use-case for the stream.
+     *
+     * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle),
+     * though 0 (no zoom) to 1 (maximum zoom).
+     * @return retval OK if the call is successful, an error code otherwise.
+     * @hide
+     */
+    int setMicrophoneFieldDimension(float zoom);
+}
diff --git a/media/java/android/media/Session2Link.java b/media/java/android/media/Session2Link.java
index 5fe558d..08664aa 100644
--- a/media/java/android/media/Session2Link.java
+++ b/media/java/android/media/Session2Link.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.annotation.NonNull;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -145,8 +146,9 @@
     }
 
     /** Stub implementation for IMediaSession2.connect */
-    public void onConnect(final Controller2Link caller, int seq, Bundle connectionRequest) {
-        mSession.onConnect(caller, seq, connectionRequest);
+    public void onConnect(final Controller2Link caller, int pid, int uid, int seq,
+            Bundle connectionRequest) {
+        mSession.onConnect(caller, pid, uid, seq, connectionRequest);
     }
 
     /** Stub implementation for IMediaSession2.disconnect */
@@ -168,23 +170,57 @@
     private class Session2Stub extends IMediaSession2.Stub {
         @Override
         public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
-            Session2Link.this.onConnect(caller, seq, connectionRequest);
+            if (caller == null || connectionRequest == null) {
+                return;
+            }
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                Session2Link.this.onConnect(caller, pid, uid, seq, connectionRequest);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         @Override
         public void disconnect(final Controller2Link caller, int seq) {
-            Session2Link.this.onDisconnect(caller, seq);
+            if (caller == null) {
+                return;
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                Session2Link.this.onDisconnect(caller, seq);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         @Override
         public void sendSessionCommand(final Controller2Link caller, final int seq,
                 final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
-            Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver);
+            if (caller == null) {
+                return;
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         @Override
         public void cancelSessionCommand(final Controller2Link caller, final int seq) {
-            Session2Link.this.onCancelCommand(caller, seq);
+            if (caller == null) {
+                return;
+            }
+            final long token = Binder.clearCallingIdentity();
+            try {
+                Session2Link.this.onCancelCommand(caller, seq);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
     }
 }
diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java
index 95ee4c0..c7b8911 100644
--- a/media/java/android/media/Session2Token.java
+++ b/media/java/android/media/Session2Token.java
@@ -152,9 +152,7 @@
         mType = in.readInt();
         mPackageName = in.readString();
         mServiceName = in.readString();
-        // TODO: Uncomment below and stop hardcode mSessionLink
-        mSessionLink = null;
-        //mSessionLink = ISession.Stub.asInterface(in.readStrongBinder());
+        mSessionLink = Session2Link.CREATOR.createFromParcel(in);
         mComponentName = ComponentName.unflattenFromString(in.readString());
     }
 
@@ -164,8 +162,7 @@
         dest.writeInt(mType);
         dest.writeString(mPackageName);
         dest.writeString(mServiceName);
-        // TODO: Uncomment below
-        //dest.writeStrongBinder(mSessionLink.getBinder());
+        mSessionLink.writeToParcel(dest, flags);
         dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString());
     }
 
diff --git a/media/java/android/media/session/MediaSessionProviderService.java b/media/java/android/media/session/MediaSessionProviderService.java
new file mode 100644
index 0000000..9a346ff
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionProviderService.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * Abstract class for mainline module services.
+ *
+ * @hide  // TODO: Make it as a @SystemApi
+ */
+public abstract class MediaSessionProviderService extends Service {
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // TODO: Return IMediaSessionProviderService.Stub()
+        return null;
+    }
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 452c6e1..0198470 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -84,7 +84,7 @@
 }
 
 cc_library_shared {
-    name: "libmedia2_jni",
+    name: "libmediaplayer2_jni",
 
     srcs: [
         "android_media_DataSourceCallback.cpp",
@@ -116,7 +116,10 @@
         "libz",
     ],
 
-    header_libs: ["libhardware_headers"],
+    header_libs: [
+        "libhardware_headers",
+        "libnativewindow_headers",
+    ],
 
     static_libs: [
         "libbase",
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
new file mode 100644
index 0000000..1d7d6de
--- /dev/null
+++ b/media/jni/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SRC_FILES := \
+    Media2Jni.cpp \
+
+# TODO: Move libmedia2_jni from system to media apex. Currently, libraries defined in
+#       Android.mk is not visible in apex build.
+LOCAL_MODULE:= libmedia2_jni
+LOCAL_SHARED_LIBRARIES := libdl liblog
+
+sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
+  $(ADDRESS_SANITIZER_RUNTIME_LIBRARY) \
+  $(UBSAN_RUNTIME_LIBRARY) \
+  $(TSAN_RUNTIME_LIBRARY)))
+
+# $(info Sanitizer:  $(sanitizer_runtime_libraries))
+
+ndk_libraries := $(call normalize-path-list,$(addprefix lib,$(addsuffix .so,\
+  $(NDK_PREBUILT_SHARED_LIBRARIES))))
+
+# $(info NDK:  $(ndk_libraries))
+
+LOCAL_CFLAGS += -DLINKED_LIBRARIES='"$(sanitizer_runtime_libraries):$(ndk_libraries)"'
+
+sanitizer_runtime_libraries :=
+ndk_libraries :=
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/Media2Jni.cpp b/media/jni/Media2Jni.cpp
new file mode 100644
index 0000000..6c0a65c
--- /dev/null
+++ b/media/jni/Media2Jni.cpp
@@ -0,0 +1,89 @@
+/*
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaPlayer2-JNI"
+#include "utils/Log.h"
+
+#include "jni.h"
+#include <android/dlext.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+
+extern "C" {
+  // Copied from GraphicsEnv.cpp
+  // TODO(b/37049319) Get this from a header once one exists
+  android_namespace_t* android_create_namespace(const char* name,
+                                                const char* ld_library_path,
+                                                const char* default_library_path,
+                                                uint64_t type,
+                                                const char* permitted_when_isolated_path,
+                                                android_namespace_t* parent);
+  bool android_link_namespaces(android_namespace_t* from,
+                               android_namespace_t* to,
+                               const char* shared_libs_sonames);
+  enum {
+     ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+  };
+
+}  // extern "C"
+
+static const char kApexLibPath[] =  "/apex/com.android.media/lib"
+#ifdef __LP64__
+    "64"
+#endif
+    "/";
+static const char kMediaPlayer2LibPath[] =  "/apex/com.android.media/lib"
+#ifdef __LP64__
+    "64"
+#endif
+    "/libmediaplayer2_jni.so";
+
+typedef jint (*Media2JniOnLoad)(JavaVM*, void*);
+
+JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    android_namespace_t *media2Ns = android_create_namespace("media2",
+            nullptr,  // ld_library_path
+            kApexLibPath,
+            ANDROID_NAMESPACE_TYPE_ISOLATED,
+            nullptr,  // permitted_when_isolated_path
+            nullptr); // parent
+    if (!android_link_namespaces(media2Ns, nullptr, LINKED_LIBRARIES)) {
+        ALOGE("Failed to link namespace. Failed to load extractor plug-ins in apex.");
+        return -1;
+    }
+    const android_dlextinfo dlextinfo = {
+        .flags = ANDROID_DLEXT_USE_NAMESPACE,
+        .library_namespace = media2Ns,
+    };
+    // load libmediaplayer2_jni and call JNI_OnLoad.
+    void *libHandle = android_dlopen_ext(kMediaPlayer2LibPath, RTLD_NOW | RTLD_LOCAL, &dlextinfo);
+    if (libHandle == NULL) {
+        ALOGW("couldn't dlopen(%s) %s", kMediaPlayer2LibPath, strerror(errno));
+        return -1;
+    }
+    Media2JniOnLoad media2JniOnLoad = (Media2JniOnLoad) dlsym(libHandle, "JNI_OnLoad");
+    if (!media2JniOnLoad) {
+        ALOGW("%s does not contain JNI_OnLoad()", kMediaPlayer2LibPath);
+        dlclose(libHandle);
+        return -1;
+    }
+    return media2JniOnLoad(vm, reserved);
+}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 7b07bea3..9c51996 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -648,7 +648,6 @@
 
     capabilities->getSupportedColorFormats(&colorFormats);
     capabilities->getSupportedProfileLevels(&profileLevels);
-    uint32_t flags = capabilities->getFlags();
     sp<AMessage> details = capabilities->getDetails();
 
     jobject defaultFormatObj = NULL;
@@ -687,7 +686,7 @@
 
     return env->NewObject(
             gCodecInfo.capsClazz, gCodecInfo.capsCtorId,
-            profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags,
+            profileLevelArray.get(), colorFormatsArray.get(), isEncoder,
             defaultFormatRef.get(), detailsRef.get());
 }
 
@@ -700,23 +699,28 @@
         return err;
     }
 
+    // TODO: get alias
     ScopedLocalRef<jstring> nameObject(env,
             env->NewStringUTF(codecInfo->getCodecName()));
 
+    ScopedLocalRef<jstring> canonicalNameObject(env,
+            env->NewStringUTF(codecInfo->getCodecName()));
+
+    MediaCodecInfo::Attributes attributes = codecInfo->getAttributes();
     bool isEncoder = codecInfo->isEncoder();
 
-    Vector<AString> mimes;
-    codecInfo->getSupportedMimes(&mimes);
+    Vector<AString> mediaTypes;
+    codecInfo->getSupportedMediaTypes(&mediaTypes);
 
     ScopedLocalRef<jobjectArray> capsArrayObj(env,
-        env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL));
+        env->NewObjectArray(mediaTypes.size(), gCodecInfo.capsClazz, NULL));
 
-    for (size_t i = 0; i < mimes.size(); i++) {
+    for (size_t i = 0; i < mediaTypes.size(); i++) {
         const sp<MediaCodecInfo::Capabilities> caps =
-                codecInfo->getCapabilitiesFor(mimes[i].c_str());
+                codecInfo->getCapabilitiesFor(mediaTypes[i].c_str());
 
         ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject(
-                env, mimes[i].c_str(), isEncoder, caps));
+                env, mediaTypes[i].c_str(), isEncoder, caps));
 
         env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get());
     }
@@ -729,7 +733,7 @@
             "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
 
     *codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
-            nameObject.get(), isEncoder, capsArrayObj.get());
+            nameObject.get(), canonicalNameObject.get(), attributes, capsArrayObj.get());
 
     return OK;
 }
@@ -2079,7 +2083,7 @@
     gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get());
 
     method = env->GetMethodID(clazz.get(), "<init>",
-            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
+            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ"
             "Ljava/util/Map;Ljava/util/Map;)V");
     CHECK(method != NULL);
     gCodecInfo.capsCtorId = method;
@@ -2217,7 +2221,7 @@
     { "getImage", "(ZI)Landroid/media/Image;",
       (void *)android_media_MediaCodec_getImage },
 
-    { "getName", "()Ljava/lang/String;",
+    { "getCanonicalName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
     { "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;",
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 8de11ca..cf14942 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -41,6 +41,21 @@
     return mcl;
 }
 
+static sp<MediaCodecInfo> getCodecInfo(JNIEnv *env, jint index) {
+    sp<IMediaCodecList> mcl = getCodecList(env);
+    if (mcl == NULL) {
+        // Runtime exception already pending.
+        return NULL;
+    }
+
+    sp<MediaCodecInfo> info = mcl->getCodecInfo(index);
+    if (info == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+    }
+
+    return info;
+}
+
 static jint android_media_MediaCodecList_getCodecCount(
         JNIEnv *env, jobject /* thiz */) {
     sp<IMediaCodecList> mcl = getCodecList(env);
@@ -53,15 +68,22 @@
 
 static jstring android_media_MediaCodecList_getCodecName(
         JNIEnv *env, jobject /* thiz */, jint index) {
-    sp<IMediaCodecList> mcl = getCodecList(env);
-    if (mcl == NULL) {
+    sp<MediaCodecInfo> info = getCodecInfo(env, index);
+    if (info == NULL) {
         // Runtime exception already pending.
         return NULL;
     }
 
-    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    // TODO: support aliases
+    const char *name = info->getCodecName();
+    return env->NewStringUTF(name);
+}
+
+static jstring android_media_MediaCodecList_getCanonicalName(
+        JNIEnv *env, jobject /* thiz */, jint index) {
+    sp<MediaCodecInfo> info = getCodecInfo(env, index);
     if (info == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        // Runtime exception already pending.
         return NULL;
     }
 
@@ -94,39 +116,27 @@
     return ret;
 }
 
-static jboolean android_media_MediaCodecList_isEncoder(
+static jboolean android_media_MediaCodecList_getAttributes(
         JNIEnv *env, jobject /* thiz */, jint index) {
-    sp<IMediaCodecList> mcl = getCodecList(env);
-    if (mcl == NULL) {
-        // Runtime exception already pending.
-        return false;
-    }
-
-    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
+    sp<MediaCodecInfo> info = getCodecInfo(env, index);
     if (info == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return false;
+        // Runtime exception already pending.
+        return 0;
     }
 
-    return info->isEncoder();
+    return info->getAttributes();
 }
 
 static jarray android_media_MediaCodecList_getSupportedTypes(
         JNIEnv *env, jobject /* thiz */, jint index) {
-    sp<IMediaCodecList> mcl = getCodecList(env);
-    if (mcl == NULL) {
+    sp<MediaCodecInfo> info = getCodecInfo(env, index);
+    if (info == NULL) {
         // Runtime exception already pending.
         return NULL;
     }
 
-    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
-    if (info == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return NULL;
-    }
-
     Vector<AString> types;
-    info->getSupportedMimes(&types);
+    info->getSupportedMediaTypes(&types);
 
     jclass clazz = env->FindClass("java/lang/String");
     CHECK(clazz != NULL);
@@ -150,17 +160,12 @@
         return NULL;
     }
 
-    sp<IMediaCodecList> mcl = getCodecList(env);
-    if (mcl == NULL) {
+    sp<MediaCodecInfo> info = getCodecInfo(env, index);
+    if (info == NULL) {
         // Runtime exception already pending.
         return NULL;
     }
 
-    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
-    if (info == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-        return NULL;
-    }
 
     const char *typeStr = env->GetStringUTFChars(type, NULL);
     if (typeStr == NULL) {
@@ -186,7 +191,6 @@
 
     capabilities->getSupportedColorFormats(&colorFormats);
     capabilities->getSupportedProfileLevels(&profileLevels);
-    uint32_t flags = capabilities->getFlags();
     sp<AMessage> details = capabilities->getDetails();
     bool isEncoder = info->isEncoder();
 
@@ -240,11 +244,11 @@
     }
 
     jmethodID capsConstructID = env->GetMethodID(capsClazz, "<init>",
-            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
+            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ"
             "Ljava/util/Map;Ljava/util/Map;)V");
 
     jobject caps = env->NewObject(capsClazz, capsConstructID,
-            profileLevelArray, colorFormatsArray, isEncoder, flags,
+            profileLevelArray, colorFormatsArray, isEncoder,
             defaultFormatObj, infoObj);
 
     env->DeleteLocalRef(profileLevelArray);
@@ -288,9 +292,15 @@
 
 static const JNINativeMethod gMethods[] = {
     { "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
+
+    { "getCanonicalName", "(I)Ljava/lang/String;",
+      (void *)android_media_MediaCodecList_getCanonicalName },
+
     { "getCodecName", "(I)Ljava/lang/String;",
       (void *)android_media_MediaCodecList_getCodecName },
-    { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder },
+
+    { "getAttributes", "(I)I", (void *)android_media_MediaCodecList_getAttributes },
+
     { "getSupportedTypes", "(I)[Ljava/lang/String;",
       (void *)android_media_MediaCodecList_getSupportedTypes },
 
diff --git a/media/packages/MediaCore/Android.bp b/media/packages/MediaCore/Android.bp
new file mode 100644
index 0000000..c7fd58b
--- /dev/null
+++ b/media/packages/MediaCore/Android.bp
@@ -0,0 +1,21 @@
+android_app {
+    name: "MediaCore",
+
+    srcs: [
+        "src/**/*.java",
+    ],
+
+    static_libs: [
+        // TODO: Temporarily statically linked. Should go into "libs"
+        "media1",
+    ],
+
+    // System app
+    platform_apis: true,
+
+    // Privileged app
+    privileged: true,
+
+    // Make sure that the implementation only relies on SDK or system APIs.
+    sdk_version: "system_current",
+}
diff --git a/media/packages/MediaCore/AndroidManifest.xml b/media/packages/MediaCore/AndroidManifest.xml
new file mode 100644
index 0000000..4e2b274
--- /dev/null
+++ b/media/packages/MediaCore/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/AndroidManifest.xml
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.media" coreApp="true" android:sharedUserId="android.uid.system"
+    android:sharedUserLabel="@string/android_system_label">
+    <application android:process="system"
+        android:persistent="true"
+        android:directBootAware="true">
+        <service android:name="AmlMediaSessionProviderService" android:singleUser="true">
+            <intent-filter>
+                <action android:name="android.media.session.MediaSessionProviderService"/>
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
diff --git a/media/packages/MediaCore/res/values/strings.xml b/media/packages/MediaCore/res/values/strings.xml
new file mode 100644
index 0000000..59fd635
--- /dev/null
+++ b/media/packages/MediaCore/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <!-- Label for the Android system components when they are shown to the user. -->
+    <string name="android_system_label" translatable="false">Android System</string>
+</resources>
+
diff --git a/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
new file mode 100644
index 0000000..43b95ab
--- /dev/null
+++ b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.media;
+
+import android.content.Context;
+import android.media.session.MediaSessionProviderService;
+import android.os.PowerManager;
+import android.util.Log;
+
+/**
+ * System implementation of MediaSessionProviderService
+ */
+public class AmlMediaSessionProviderService extends MediaSessionProviderService {
+    private static final String TAG = "AmlMediaSessionProviderS";
+    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private Context mContext;
+
+    public AmlMediaSessionProviderService(Context context) {
+        mContext = context;
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+    }
+}
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 8e58210..c3b2e25 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -342,3 +342,8 @@
     RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP);
     return static_cast<Sensor const *>(sensor)->getHighestDirectReportRateLevel();
 }
+
+int ASensor_getHandle(ASensor const* sensor) {
+    RETURN_IF_SENSOR_IS_NULL(ASENSOR_INVALID);
+    return static_cast<Sensor const*>(sensor)->getHandle();
+}
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index bb2ee9b..0490e65 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -74,7 +74,10 @@
   VkQueue queue;
   uint32_t graphics_queue_index;
   uint32_t instance_version;
-  const char* const* enabled_extension_names;
+  const char* const* enabled_instance_extension_names;
+  uint32_t enabled_instance_extension_names_length;
+  const char* const* enabled_device_extension_names;
+  uint32_t enabled_device_extension_names_length;
   // Only one of device_features and device_features_2 should be non-null.
   // If both are null then no features are enabled.
   VkPhysicalDeviceFeatures* device_features;
@@ -128,15 +131,13 @@
 
 struct AwDrawFn_PostDrawVkParams {
   int version;
-
-  // Input: Fence for the composite command buffer to signal it has finished its
-  // work on the GPU.
-  int fd;
 };
 
 // Called on render thread while UI thread is blocked. Called for both GL and
 // VK.
-typedef void AwDrawFn_OnSync(int functor, void* data, AwDrawFn_OnSyncParams* params);
+typedef void AwDrawFn_OnSync(int functor,
+                             void* data,
+                             AwDrawFn_OnSyncParams* params);
 
 // Called on render thread when either the context is destroyed _or_ when the
 // functor's last reference goes away. Will always be called with an active
@@ -150,17 +151,24 @@
 typedef void AwDrawFn_OnDestroyed(int functor, void* data);
 
 // Only called for GL.
-typedef void AwDrawFn_DrawGL(int functor, void* data, AwDrawFn_DrawGLParams* params);
+typedef void AwDrawFn_DrawGL(int functor,
+                             void* data,
+                             AwDrawFn_DrawGLParams* params);
 
 // Initialize vulkan state. Needs to be called again after any
 // OnContextDestroyed. Only called for Vulkan.
-typedef void AwDrawFn_InitVk(int functor, void* data, AwDrawFn_InitVkParams* params);
+typedef void AwDrawFn_InitVk(int functor,
+                             void* data,
+                             AwDrawFn_InitVkParams* params);
 
 // Only called for Vulkan.
-typedef void AwDrawFn_DrawVk(int functor, void* data, AwDrawFn_DrawVkParams* params);
+typedef void AwDrawFn_DrawVk(int functor,
+                             void* data,
+                             AwDrawFn_DrawVkParams* params);
 
 // Only called for Vulkan.
-typedef void AwDrawFn_PostDrawVk(int functor, void* data,
+typedef void AwDrawFn_PostDrawVk(int functor,
+                                 void* data,
                                  AwDrawFn_PostDrawVkParams* params);
 
 struct AwDrawFnFunctorCallbacks {
@@ -183,7 +191,8 @@
 typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void);
 
 // Create a functor. |functor_callbacks| should be valid until OnDestroyed.
-typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks);
+typedef int AwDrawFn_CreateFunctor(void* data,
+                                   AwDrawFnFunctorCallbacks* functor_callbacks);
 
 // May be called on any thread to signal that the functor should be destroyed.
 // The functor will receive an onDestroyed when the last usage of it is
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index 6c1ceab..b97bbc3 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -74,6 +74,79 @@
   support->callbacks.draw_gl(functor, support->data, &params);
 }
 
+void initializeVk(int functor, void* data,
+                  const uirenderer::VkFunctorInitParams& init_vk_params) {
+  SupportData* support = static_cast<SupportData*>(data);
+  VkPhysicalDeviceFeatures2 device_features_2;
+  if (init_vk_params.device_features_2)
+    device_features_2 = *init_vk_params.device_features_2;
+
+  AwDrawFn_InitVkParams params{
+      .version = kAwDrawFnVersion,
+      .instance = init_vk_params.instance,
+      .physical_device = init_vk_params.physical_device,
+      .device = init_vk_params.device,
+      .queue = init_vk_params.queue,
+      .graphics_queue_index = init_vk_params.graphics_queue_index,
+      .instance_version = init_vk_params.instance_version,
+      .enabled_instance_extension_names =
+          init_vk_params.enabled_instance_extension_names,
+      .enabled_instance_extension_names_length =
+          init_vk_params.enabled_instance_extension_names_length,
+      .enabled_device_extension_names =
+          init_vk_params.enabled_device_extension_names,
+      .enabled_device_extension_names_length =
+          init_vk_params.enabled_device_extension_names_length,
+      .device_features = nullptr,
+      .device_features_2 =
+          init_vk_params.device_features_2 ? &device_features_2 : nullptr,
+  };
+  support->callbacks.init_vk(functor, support->data, &params);
+}
+
+void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw_vk_params) {
+  SupportData* support = static_cast<SupportData*>(data);
+  float gabcdef[7];
+  draw_vk_params.color_space_ptr->transferFn(gabcdef);
+  AwDrawFn_DrawVkParams params{
+      .version = kAwDrawFnVersion,
+      .width = draw_vk_params.width,
+      .height = draw_vk_params.height,
+      .is_layer = draw_vk_params.is_layer,
+      .secondary_command_buffer = draw_vk_params.secondary_command_buffer,
+      .color_attachment_index = draw_vk_params.color_attachment_index,
+      .compatible_render_pass = draw_vk_params.compatible_render_pass,
+      .format = draw_vk_params.format,
+      .transfer_function_g = gabcdef[0],
+      .transfer_function_a = gabcdef[1],
+      .transfer_function_b = gabcdef[2],
+      .transfer_function_c = gabcdef[3],
+      .transfer_function_d = gabcdef[4],
+      .transfer_function_e = gabcdef[5],
+      .transfer_function_f = gabcdef[6],
+      .clip_left = draw_vk_params.clip_left,
+      .clip_top = draw_vk_params.clip_top,
+      .clip_right = draw_vk_params.clip_right,
+      .clip_bottom = draw_vk_params.clip_bottom,
+  };
+  COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3),
+                 gamut_transform_size_mismatch);
+  draw_vk_params.color_space_ptr->toXYZD50(
+      reinterpret_cast<skcms_Matrix3x3*>(&params.color_space_toXYZD50));
+  COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_vk_params.transform),
+                 mismatched_transform_matrix_sizes);
+  for (int i = 0; i < NELEM(params.transform); ++i) {
+    params.transform[i] = draw_vk_params.transform[i];
+  }
+  support->callbacks.draw_vk(functor, support->data, &params);
+}
+
+void postDrawVk(int functor, void* data) {
+  SupportData* support = static_cast<SupportData*>(data);
+  AwDrawFn_PostDrawVkParams params{.version = kAwDrawFnVersion};
+  support->callbacks.post_draw_vk(functor, support->data, &params);
+}
+
 int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
   static bool callbacks_initialized = false;
   static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = {
@@ -82,9 +155,19 @@
       .onDestroyed = &onDestroyed,
   };
   if (!callbacks_initialized) {
-    // Under uirenderer::RenderMode::Vulkan, whether gles or vk union should
-    // be populated should match whether the vk-gl interop is used.
-    webview_functor_callbacks.gles.draw = &draw_gl;
+    switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) {
+      case uirenderer::RenderMode::OpenGL_ES:
+        webview_functor_callbacks.gles.draw = &draw_gl;
+        break;
+      case uirenderer::RenderMode::Vulkan:
+        webview_functor_callbacks.vk.initialize = &initializeVk;
+        webview_functor_callbacks.vk.draw = &drawVk;
+        webview_functor_callbacks.vk.postDraw = &postDrawVk;
+        // TODO(boliu): Remove this once SkiaRecordingCanvas::drawWebViewFunctor
+        // no longer uses GL interop.
+        webview_functor_callbacks.gles.draw = &draw_gl;
+        break;
+    }
     callbacks_initialized = true;
   }
   SupportData* support = new SupportData{
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a29cf84..16bfcc9 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -103,6 +103,8 @@
     <string name="ssid_by_passpoint_provider"><xliff:g id="ssid" example="Cafe Wifi">%1$s</xliff:g> by <xliff:g id="passpointProvider" example="Passpoint Provider">%2$s</xliff:g></string>
     <!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
     <string name="available_via_passpoint">Available via %1$s</string>
+    <!-- Status message of OSU Provider network when not connected. [CHAR LIMIT=NONE] -->
+    <string name="tap_to_set_up">Tap to set up</string>
     <!-- Package name for Settings app-->
     <string name="settings_package" translatable="false">com.android.settings</string>
     <!-- Package name for Certinstaller app-->
@@ -125,6 +127,79 @@
     <!-- Status message of Wi-Fi when an available network is a carrier network. [CHAR LIMIT=NONE] -->
     <string name="available_via_carrier">Available via %1$s</string>
 
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_AP_CONNECTION. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_ap_connection">Connection failed</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_URL_INVALID. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_server_url_invalid">Invalid OSU server URL</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_CONNECTION. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_server_connection">OSU server connection failed</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVER_VALIDATION. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_server_validation">OSU server validation failed</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_service_provider_verification">Invalid OSU server certificate</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_PROVISIONING_ABORTED. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_provisioning_aborted">Provisioning aborted</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_PROVISIONING_NOT_AVAILABLE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_provisioning_not_available">Provisioning not available</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_INVALID_SERVER_URL. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_invalid_server_url">Invalid OSU server URL</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_COMMAND_TYPE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_unexpected_command_type">Unexpected command type</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_unexpected_soap_message_type">Unexpected SOAP message type</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_SOAP_MESSAGE_EXCHANGE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_soap_message_exchange">SOAP message exchange failed</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_START_REDIRECT_LISTENER. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_start_redirect_listener">Redirect listener failed to start</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_timed_out_redirect_listener">Timed out waiting for redirect</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_OSU_ACTIVITY_FOUND. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_osu_activity_found">No OSU activity found</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_unexpected_soap_message_status">Unexpected SOAP message status</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_PPS_MO. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_pps_mo">Failed to find PPS-MO</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_aaa_server_trust_root_node">Failed to find trust root node for AAA server</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_remediation_server_trust_root_node">Failed to find trust root node for remediation server</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_policy_server_trust_root_node">Failed to find trust root node for policy server</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_retrieve_trust_root_certificates">Failed to retrieve trust root certificates</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_no_aaa_trust_root_certificate">Failed to find trust root certificate for AAA server</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_add_passpoint_configuration">Failed to add PassPoint configuration</string>
+    <!-- Status message of OSU Provider on receiving OSU_FAILURE_OSU_PROVIDER_NOT_FOUND. [CHAR LIMIT=NONE] -->
+    <string name="osu_failure_osu_provider_not_found">Failed to find an OSU provider</string>
+
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_AP_CONNECTING. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_ap_connecting">Connecting</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_AP_CONNECTED. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_ap_connected">Connected</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_CONNECTING. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_server_connecting">Connecting to OSU server</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_VALIDATED. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_server_validated">OSU server validated</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_SERVER_CONNECTED. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_server_connected">Connected to OSU server</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_INIT_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_init_soap_exchange">Initial SOAP exchange</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_waiting_for_redirect_response">Waiting for redirect response</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_REDIRECT_RESPONSE_RECEIVED. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_redirect_response_received">Received redirect response</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_SECOND_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_second_soap_exchange">Second SOAP exchange</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_THIRD_SOAP_EXCHANGE. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_third_soap_exchange">Third SOAP exchange</string>
+    <!-- Status message of OSU Provider on receiving OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS. [CHAR LIMIT=NONE] -->
+    <string name="osu_status_retrieving_trust_root_certs">Retrieving trust root certificates</string>
+
+    <!-- Status message of OSU Provider on completing provisioning. [CHAR LIMIT=NONE] -->
+    <string name="osu_provisioning_complete">Provisioning complete</string>
+
     <!-- Speed label for very slow network speed -->
     <string name="speed_label_very_slow">Very Slow</string>
     <!-- Speed label for slow network speed -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 595aeb3..c751c39 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -38,8 +38,8 @@
     private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
     private static final String NEW_MODE_KEY = "NEW_MODE";
     @VisibleForTesting
-    static final String STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY =
-            "ro.storage_manager.show_opt_in";
+    static final String STORAGE_MANAGER_ENABLED_PROPERTY =
+            "ro.storage_manager.enabled";
 
     private static Signature[] sSystemSignature;
     private static String sPermissionControllerPackageName;
@@ -373,8 +373,7 @@
     public static boolean isStorageManagerEnabled(Context context) {
         boolean isDefaultOn;
         try {
-            // Turn off by default if the opt-in was shown.
-            isDefaultOn = !SystemProperties.getBoolean(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, true);
+            isDefaultOn = SystemProperties.getBoolean(STORAGE_MANAGER_ENABLED_PROPERTY, false);
         } catch (Resources.NotFoundException e) {
             isDefaultOn = false;
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index 12b8efb..4ab9a9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -55,6 +55,12 @@
             "com.android.settings.category.ia.privacy";
     public static final String CATEGORY_ENTERPRISE_PRIVACY =
             "com.android.settings.category.ia.enterprise_privacy";
+    public static final String CATEGORY_ABOUT_LEGAL =
+            "com.android.settings.category.ia.about_legal";
+    public static final String CATEGORY_MY_DEVICE_INFO =
+            "com.android.settings.category.ia.my_device_info";
+    public static final String CATEGORY_BATTERY_SAVER_SETTINGS =
+            "com.android.settings.category.ia.battery_saver_settings";
 
     public static final Map<String, String> KEY_COMPAT_MAP;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 1ae1d56..27dc628 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -43,6 +43,7 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -219,6 +220,11 @@
     private boolean mIsCarrierAp = false;
 
     private OsuProvider mOsuProvider;
+
+    private String mOsuStatus;
+    private String mOsuFailure;
+    private boolean mOsuProvisioningComplete = false;
+
     /**
      * The EAP type {@link WifiEnterpriseConfig.Eap} associated with this AP if it is a carrier AP.
      */
@@ -315,9 +321,7 @@
     public AccessPoint(Context context, OsuProvider provider) {
         mContext = context;
         mOsuProvider = provider;
-        mRssi = 1;
-        // TODO: This placeholder SSID is here to avoid null pointer exceptions.
-        ssid = "<OsuProvider AP SSID goes here>";
+        ssid = provider.getFriendlyName();
         updateKey();
     }
 
@@ -358,24 +362,13 @@
     /** Updates {@link #mKey} and should only called upon object creation/initialization. */
     private void updateKey() {
         // TODO(sghuman): Consolidate Key logic on ScanResultMatchInfo
-
-        StringBuilder builder = new StringBuilder();
-
         if (isPasspoint()) {
-            builder.append(KEY_PREFIX_FQDN).append(mConfig.FQDN);
+            mKey = getKey(mConfig);
         } else if (isOsuProvider()) {
-            builder.append(KEY_PREFIX_OSU).append(mOsuProvider.getOsuSsid());
-            builder.append(',').append(mOsuProvider.getServerUri());
+            mKey = getKey(mOsuProvider);
         } else { // Non-Passpoint AP
-            builder.append(KEY_PREFIX_AP);
-            if (TextUtils.isEmpty(getSsidStr())) {
-                builder.append(getBssid());
-            } else {
-                builder.append(getSsidStr());
-            }
-            builder.append(',').append(getSecurity());
+            mKey = getKey(getSsidStr(), getBssid(), getSecurity());
         }
-        mKey = builder.toString();
     }
 
     /**
@@ -616,34 +609,46 @@
     }
 
     public static String getKey(ScanResult result) {
-        StringBuilder builder = new StringBuilder();
-
-        builder.append(KEY_PREFIX_AP);
-        if (TextUtils.isEmpty(result.SSID)) {
-            builder.append(result.BSSID);
-        } else {
-            builder.append(result.SSID);
-        }
-
-        builder.append(',').append(getSecurity(result));
-        return builder.toString();
+        return getKey(result.SSID, result.BSSID, getSecurity(result));
     }
 
+    /**
+     * Returns the AccessPoint key for a WifiConfiguration.
+     * This will return a special Passpoint key if the config is for Passpoint.
+     */
     public static String getKey(WifiConfiguration config) {
-        StringBuilder builder = new StringBuilder();
-
         if (config.isPasspoint()) {
-            builder.append(KEY_PREFIX_FQDN).append(config.FQDN);
+            return new StringBuilder()
+                    .append(KEY_PREFIX_FQDN)
+                    .append(config.FQDN).toString();
         } else {
-            builder.append(KEY_PREFIX_AP);
-            if (TextUtils.isEmpty(config.SSID)) {
-                builder.append(config.BSSID);
-            } else {
-                builder.append(removeDoubleQuotes(config.SSID));
-            }
-            builder.append(',').append(getSecurity(config));
+            return getKey(config.SSID, config.BSSID, getSecurity(config));
         }
+    }
 
+    /**
+     * Returns the AccessPoint key corresponding to the OsuProvider.
+     */
+    public static String getKey(OsuProvider provider) {
+        return new StringBuilder()
+                .append(KEY_PREFIX_OSU)
+                .append(provider.getFriendlyName())
+                .append(',')
+                .append(provider.getServerUri()).toString();
+    }
+
+    /**
+     * Returns the AccessPoint key for a normal non-Passpoint network by ssid/bssid and security.
+     */
+    private static String getKey(String ssid, String bssid, int security) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(KEY_PREFIX_AP);
+        if (TextUtils.isEmpty(ssid)) {
+            builder.append(bssid);
+        } else {
+            builder.append(ssid);
+        }
+        builder.append(',').append(security);
         return builder.toString();
     }
 
@@ -881,7 +886,17 @@
         // Update to new summary
         StringBuilder summary = new StringBuilder();
 
-        if (isActive()) {
+        if (isOsuProvider()) {
+            if (mOsuProvisioningComplete) {
+                summary.append(mContext.getString(R.string.osu_provisioning_complete));
+            } else if (mOsuFailure != null) {
+                summary.append(mOsuFailure);
+            } else if (mOsuStatus != null) {
+                summary.append(mOsuStatus);
+            } else {
+                summary.append(mContext.getString(R.string.tap_to_set_up));
+            }
+        } else if (isActive()) {
             if (isPasspoint()) {
                 // This is the active connection on passpoint
                 summary.append(getSummary(mContext, ssid, getDetailedState(),
@@ -1014,11 +1029,26 @@
     }
 
     /**
+     * Starts the OSU Provisioning flow.
+     */
+    public void startOsuProvisioning() {
+        mContext.getSystemService(WifiManager.class).startSubscriptionProvisioning(
+                mOsuProvider,
+                new AccessPointProvisioningCallback(),
+                ThreadUtils.getUiThreadHandler()
+        );
+    }
+
+    /**
      * Return whether the given {@link WifiInfo} is for this access point.
      * If the current AP does not have a network Id then the config is used to
      * match based on SSID and security.
      */
     private boolean isInfoForThisAccessPoint(WifiConfiguration config, WifiInfo info) {
+        if (info.isOsuAp()) {
+            return (mOsuStatus != null);
+        }
+
         if (isPasspoint() == false && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
             return networkId == info.getNetworkId();
         } else if (config != null) {
@@ -1491,4 +1521,166 @@
     private static boolean isVerboseLoggingEnabled() {
         return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
     }
+
+    /**
+     * Callbacks relaying changes to the OSU provisioning status started in startOsuProvisioning().
+     *
+     * All methods are invoked on the Main Thread
+     */
+    private class AccessPointProvisioningCallback extends ProvisioningCallback {
+        // TODO: Remove logs and implement summary changing logic for these provisioning callbacks.
+        @Override
+        @MainThread public void onProvisioningFailure(int status) {
+            switch (status) {
+                case OSU_FAILURE_AP_CONNECTION:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_ap_connection);
+                    break;
+                case OSU_FAILURE_SERVER_URL_INVALID:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_server_url_invalid);
+                    break;
+                case OSU_FAILURE_SERVER_CONNECTION:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_server_connection);
+                    break;
+                case OSU_FAILURE_SERVER_VALIDATION:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_server_validation);
+                    break;
+                case OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_service_provider_verification);
+                    break;
+                case OSU_FAILURE_PROVISIONING_ABORTED:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_provisioning_aborted);
+                    break;
+                case OSU_FAILURE_PROVISIONING_NOT_AVAILABLE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_provisioning_not_available);
+                    break;
+                case OSU_FAILURE_INVALID_SERVER_URL:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_invalid_server_url);
+                    break;
+                case OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_unexpected_command_type);
+                    break;
+                case OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_unexpected_soap_message_type);
+                    break;
+                case OSU_FAILURE_SOAP_MESSAGE_EXCHANGE:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_soap_message_exchange);
+                    break;
+                case OSU_FAILURE_START_REDIRECT_LISTENER:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_start_redirect_listener);
+                    break;
+                case OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_timed_out_redirect_listener);
+                    break;
+                case OSU_FAILURE_NO_OSU_ACTIVITY_FOUND:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_no_osu_activity_found);
+                    break;
+                case OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_unexpected_soap_message_status);
+                    break;
+                case OSU_FAILURE_NO_PPS_MO:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_no_pps_mo);
+                    break;
+                case OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_no_aaa_server_trust_root_node);
+                    break;
+                case OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_no_remediation_server_trust_root_node);
+                    break;
+                case OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_no_policy_server_trust_root_node);
+                    break;
+                case OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_retrieve_trust_root_certificates);
+                    break;
+                case OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_no_aaa_trust_root_certificate);
+                    break;
+                case OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION:
+                    mOsuFailure = mContext.getString(
+                            R.string.osu_failure_add_passpoint_configuration);
+                    break;
+                case OSU_FAILURE_OSU_PROVIDER_NOT_FOUND:
+                    mOsuFailure = mContext.getString(R.string.osu_failure_osu_provider_not_found);
+                    break;
+            }
+            mOsuStatus = null;
+            mOsuProvisioningComplete = false;
+            ThreadUtils.postOnMainThread(() -> {
+                if (mAccessPointListener != null) {
+                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
+                }
+            });
+        }
+
+        @Override
+        @MainThread public void onProvisioningStatus(int status) {
+            switch (status) {
+                case OSU_STATUS_AP_CONNECTING:
+                    mOsuStatus = mContext.getString(R.string.osu_status_ap_connecting);
+                    break;
+                case OSU_STATUS_AP_CONNECTED:
+                    mOsuStatus = mContext.getString(R.string.osu_status_ap_connected);
+                    break;
+                case OSU_STATUS_SERVER_CONNECTING:
+                    mOsuStatus = mContext.getString(R.string.osu_status_server_connecting);
+                    break;
+                case OSU_STATUS_SERVER_VALIDATED:
+                    mOsuStatus = mContext.getString(R.string.osu_status_server_validated);
+                    break;
+                case OSU_STATUS_SERVER_CONNECTED:
+                    mOsuStatus = mContext.getString(R.string.osu_status_server_connected);
+                    break;
+                case OSU_STATUS_INIT_SOAP_EXCHANGE:
+                    mOsuStatus = mContext.getString(R.string.osu_status_init_soap_exchange);
+                    break;
+                case OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE:
+                    mOsuStatus = mContext.getString(
+                            R.string.osu_status_waiting_for_redirect_response);
+                    break;
+                case OSU_STATUS_REDIRECT_RESPONSE_RECEIVED:
+                    mOsuStatus = mContext.getString(R.string.osu_status_redirect_response_received);
+                    break;
+                case OSU_STATUS_SECOND_SOAP_EXCHANGE:
+                    mOsuStatus = mContext.getString(R.string.osu_status_second_soap_exchange);
+                    break;
+                case OSU_STATUS_THIRD_SOAP_EXCHANGE:
+                    mOsuStatus = mContext.getString(R.string.osu_status_third_soap_exchange);
+                    break;
+                case OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS:
+                    mOsuStatus = mContext.getString(
+                            R.string.osu_status_retrieving_trust_root_certs);
+                    break;
+            }
+            mOsuFailure = null;
+            mOsuProvisioningComplete = false;
+            ThreadUtils.postOnMainThread(() -> {
+                if (mAccessPointListener != null) {
+                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
+                }
+            });
+        }
+
+        @Override
+        @MainThread public void onProvisioningComplete() {
+            mOsuProvisioningComplete = true;
+            mOsuFailure = null;
+            mOsuStatus = null;
+            ThreadUtils.postOnMainThread(() -> {
+                if (mAccessPointListener != null) {
+                    mAccessPointListener.onAccessPointChanged(AccessPoint.this);
+                }
+            });
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 6d28891..b9a5f23 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -68,6 +68,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -585,7 +586,6 @@
                     Map<Integer, List<ScanResult>>> pairing : passpointConfigsAndScans) {
                 WifiConfiguration config = pairing.first;
 
-                // TODO(b/118705403): Prioritize home networks before roaming networks
                 List<ScanResult> scanResults = new ArrayList<>();
 
                 List<ScanResult> homeScans =
@@ -600,8 +600,12 @@
                     roamingScans = new ArrayList<>();
                 }
 
-                scanResults.addAll(homeScans);
-                scanResults.addAll(roamingScans);
+                // TODO(b/118705403): Differentiate home network vs roaming network for summary info
+                if (!homeScans.isEmpty()) {
+                    scanResults.addAll(homeScans);
+                } else {
+                    scanResults.addAll(roamingScans);
+                }
 
                 if (seenFQDNs.add(config.FQDN)) {
                     int bestRssi = Integer.MIN_VALUE;
@@ -612,27 +616,27 @@
                         }
                     }
 
-                    AccessPoint accessPoint = new AccessPoint(mContext, config);
-                    accessPoint.setScanResults(scanResults);
+                    AccessPoint accessPoint =
+                            getCachedOrCreatePasspoint(scanResults, cachedAccessPoints, config);
                     accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                     accessPoints.add(accessPoint);
                 }
             }
 
             // Add Passpoint OSU Provider AccessPoints
-            // TODO(b/118705403): filter out OSU Providers which we already have credentials from.
             Map<OsuProvider, List<ScanResult>> providersAndScans =
                     mWifiManager.getMatchingOsuProviders(cachedScanResults);
+            Set<OsuProvider> alreadyProvisioned = mWifiManager
+                    .getMatchingPasspointConfigsForOsuProviders(
+                            providersAndScans.keySet()).keySet();
             for (OsuProvider provider : providersAndScans.keySet()) {
-                AccessPoint accessPointOsu = new AccessPoint(mContext, provider);
-                // TODO(b/118705403): accessPointOsu.setScanResults(Matching ScanResult with best
-                // RSSI)
-                // TODO(b/118705403): Figure out if we would need to update an OSU AP (this will be
-                // used if we need to display it at the top of the picker as the "active" AP).
-                // Otherwise, OSU APs should ignore attempts to update the active connection
-                // info.
-                // accessPointOsu.update(connectionConfig, mLastInfo, mLastNetworkInfo);
-                accessPoints.add(accessPointOsu);
+                if (!alreadyProvisioned.contains(provider)) {
+                    AccessPoint accessPointOsu =
+                            getCachedOrCreateOsu(providersAndScans.get(provider),
+                                    cachedAccessPoints, provider);
+                    accessPointOsu.update(connectionConfig, mLastInfo, mLastNetworkInfo);
+                    accessPoints.add(accessPointOsu);
+                }
             }
 
 
@@ -685,16 +689,49 @@
     AccessPoint getCachedOrCreate(
             List<ScanResult> scanResults,
             List<AccessPoint> cache) {
-        final int N = cache.size();
-        for (int i = 0; i < N; i++) {
-            if (cache.get(i).getKey().equals(AccessPoint.getKey(scanResults.get(0)))) {
-                AccessPoint ret = cache.remove(i);
-                ret.setScanResults(scanResults);
-                return ret;
+        AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(scanResults.get(0)));
+        if (accessPoint == null) {
+            accessPoint = new AccessPoint(mContext, scanResults);
+        } else {
+            accessPoint.setScanResults(scanResults);
+        }
+        return accessPoint;
+    }
+
+    private AccessPoint getCachedOrCreatePasspoint(
+            List<ScanResult> scanResults,
+            List<AccessPoint> cache,
+            WifiConfiguration config) {
+        AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(config));
+        if (accessPoint == null) {
+            accessPoint = new AccessPoint(mContext, config);
+        }
+        accessPoint.setScanResults(scanResults);
+        return accessPoint;
+    }
+
+    private AccessPoint getCachedOrCreateOsu(
+            List<ScanResult> scanResults,
+            List<AccessPoint> cache,
+            OsuProvider provider) {
+        AccessPoint accessPoint = getCachedByKey(cache, AccessPoint.getKey(provider));
+        if (accessPoint == null) {
+            accessPoint = new AccessPoint(mContext, provider);
+        }
+        accessPoint.setScanResults(scanResults);
+        return accessPoint;
+    }
+
+    private AccessPoint getCachedByKey(List<AccessPoint> cache, String key) {
+        ListIterator<AccessPoint> lit = cache.listIterator();
+        while (lit.hasNext()) {
+            AccessPoint currentAccessPoint = lit.next();
+            if (currentAccessPoint.getKey().equals(key)) {
+                lit.remove();
+                return currentAccessPoint;
             }
         }
-        final AccessPoint accessPoint = new AccessPoint(mContext, scanResults);
-        return accessPoint;
+        return null;
     }
 
     private void updateNetworkInfo(NetworkInfo networkInfo) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 86f0438..92ebe44 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -17,7 +17,7 @@
 
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
-import static com.android.settingslib.Utils.STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY;
+import static com.android.settingslib.Utils.STORAGE_MANAGER_ENABLED_PROPERTY;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -159,7 +159,7 @@
 
     @Test
     public void testIsStorageManagerEnabled_UsesSystemProperties() {
-        SystemProperties.set(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, "false");
+        SystemProperties.set(STORAGE_MANAGER_ENABLED_PROPERTY, "true");
         assertThat(Utils.isStorageManagerEnabled(mContext)).isTrue();
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 18bdb20..e843eb4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -705,14 +705,17 @@
                 Settings.Global.GPU_DEBUG_LAYERS_GLES,
                 GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES);
         dumpSetting(s, p,
+                Settings.Global.GUP_DEV_ALL_APPS,
+                GlobalSettingsProto.Gpu.GUP_DEV_ALL_APPS);
+        dumpSetting(s, p,
                 Settings.Global.GUP_DEV_OPT_IN_APPS,
                 GlobalSettingsProto.Gpu.GUP_DEV_OPT_IN_APPS);
         dumpSetting(s, p,
                 Settings.Global.GUP_DEV_OPT_OUT_APPS,
                 GlobalSettingsProto.Gpu.GUP_DEV_OPT_OUT_APPS);
         dumpSetting(s, p,
-                Settings.Global.GUP_BLACK_LIST,
-                GlobalSettingsProto.Gpu.GUP_BLACK_LIST);
+                Settings.Global.GUP_BLACKLIST,
+                GlobalSettingsProto.Gpu.GUP_BLACKLIST);
         p.end(gpuToken);
 
         final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
@@ -1879,6 +1882,9 @@
         dumpSetting(s, p,
                 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
                 SecureSettingsProto.Doze.PULSE_ON_DOUBLE_TAP);
+        dumpSetting(s, p,
+                Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
+                SecureSettingsProto.Doze.PULSE_ON_TAP);
         p.end(dozeToken);
 
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index bce5593..5153f9e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1052,7 +1052,7 @@
         }
 
         // TODO(b/117663715): Ensure the caller can access the setting.
-        // enforceSettingReadable(name, SETTINGS_TYPE_CONFIG, UserHandle.getCallingUserId());
+        // enforceReadPermission(READ_DEVICE_CONFIG);
 
         // Get the value.
         synchronized (mLock) {
@@ -1088,8 +1088,9 @@
 
     private boolean mutateConfigSetting(String name, String value, String prefix,
             boolean makeDefault, int operation, int mode) {
-        // TODO(b/117663715): check the new permission when it's added.
-        // enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);
+
+        // TODO(b/117663715): Ensure the caller can access the setting.
+        // enforceReadPermission(WRITE_DEVICE_CONFIG);
 
         // Perform the mutation.
         synchronized (mLock) {
diff --git a/packages/SettingsProvider/test/AndroidManifest.xml b/packages/SettingsProvider/test/AndroidManifest.xml
index 87a4f60..ebdf9b1 100644
--- a/packages/SettingsProvider/test/AndroidManifest.xml
+++ b/packages/SettingsProvider/test/AndroidManifest.xml
@@ -20,6 +20,8 @@
     <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
 
     <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG"/>
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/>
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
     <uses-permission android:name="android.permission.MANAGE_USERS"/>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 9b775e0..b903142 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -57,6 +57,8 @@
     <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" />
     <!-- Development tool permissions granted to the shell. -->
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index afb9781..2d7471d 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -1953,8 +1953,7 @@
 
         @Override
         public void onProgress(int progress) throws RemoteException {
-            // TODO(b/111441001): change max argument?
-            updateProgressInfo(progress, CAPPED_MAX);
+            updateProgressInfo(progress, 100 /* progress is already a percentage; so max = 100 */);
         }
 
         @Override
diff --git a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
index 0d72657..6f7f398 100644
--- a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
@@ -19,15 +19,9 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
   >
-  <TextClock
+  <include
       android:id="@+id/digital_clock"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:letterSpacing="0.03"
-      android:singleLine="true"
-      style="@style/widget_big"
-      android:format12Hour="@string/keyguard_widget_12_hours_format"
-      android:format24Hour="@string/keyguard_widget_24_hours_format"
+      layout="@layout/text_clock"
   />
   <com.android.keyguard.clock.ImageClock
       android:id="@+id/analog_clock"
diff --git a/packages/SystemUI/res-keyguard/layout/digital_clock.xml b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
index cf4a573..e88e2c9 100644
--- a/packages/SystemUI/res-keyguard/layout/digital_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/digital_clock.xml
@@ -20,16 +20,9 @@
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
     android:layout_alignParentTop="true">
-  <TextClock
+  <include
       android:id="@+id/lock_screen_clock"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_gravity="center_horizontal"
-      android:letterSpacing="0.03"
-      android:singleLine="true"
-      style="@style/widget_big"
-      android:format12Hour="@string/keyguard_widget_12_hours_format"
-      android:format24Hour="@string/keyguard_widget_24_hours_format" />
+      layout="@layout/text_clock"
   />
 </FrameLayout>
 
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index d52866f..463367b 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -30,17 +30,9 @@
          android:layout_height="wrap_content"
          android:layout_gravity="center_horizontal"
          android:layout_alignParentTop="true">
-        <TextClock
+        <include
              android:id="@+id/default_clock_view"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:layout_gravity="center_horizontal"
-             android:letterSpacing="0.03"
-             android:textColor="?attr/wallpaperTextColor"
-             android:singleLine="true"
-             style="@style/widget_big"
-             android:format12Hour="@string/keyguard_widget_12_hours_format"
-             android:format24Hour="@string/keyguard_widget_24_hours_format" />
+             layout="@layout/text_clock" />
     </FrameLayout>
     <include layout="@layout/keyguard_status_area"
         android:id="@+id/keyguard_status_area"
diff --git a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
new file mode 100644
index 0000000..64b676f5
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<com.android.keyguard.clock.ClockLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+  >
+  <include
+      android:id="@+id/digital_clock"
+      layout="@layout/text_clock"
+  />
+  <com.android.keyguard.clock.StretchAnalogClock
+      android:id="@+id/analog_clock"
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+  />
+</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/text_clock.xml b/packages/SystemUI/res-keyguard/layout/text_clock.xml
new file mode 100644
index 0000000..b61ad9c
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/text_clock.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<TextClock
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal"
+    android:letterSpacing="0.03"
+    android:textColor="?attr/wallpaperTextColor"
+    android:singleLine="true"
+    style="@style/widget_big"
+    android:format12Hour="@string/keyguard_widget_12_hours_format"
+    android:format24Hour="@string/keyguard_widget_24_hours_format"
+    android:elegantTextHeight="false"
+/>
diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml
index 7f4e0d2..f932303 100644
--- a/packages/SystemUI/res/layout/global_actions_wrapped.xml
+++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <com.android.systemui.HardwareUiLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@id/global_actions_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_gravity="top|right"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 476089a..98f0cbe 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -106,7 +106,7 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast
+        wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,sensorprivacy
     </string>
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 633f868..bd34bea 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -114,5 +114,8 @@
     <item type="id" name="aod_mask_transition_progress_tag" />
     <item type="id" name="aod_mask_transition_progress_end_tag" />
     <item type="id" name="aod_mask_transition_progress_start_tag" />
+
+    <!-- Global Actions Menu -->
+    <item type="id" name="global_actions_view" />
 </resources>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 41e9eba..a055950 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -46,6 +46,7 @@
     protected View mEcaView;
     protected boolean mEnableHaptics;
     private boolean mDismissing;
+    protected boolean mResumed;
     private CountDownTimer mCountdownTimer = null;
 
     // To avoid accidental lockout due to events while the device in in the pocket, ignore
@@ -263,6 +264,8 @@
 
     @Override
     public void onPause() {
+        mResumed = false;
+
         if (mCountdownTimer != null) {
             mCountdownTimer.cancel();
             mCountdownTimer = null;
@@ -276,6 +279,7 @@
 
     @Override
     public void onResume(int reason) {
+        mResumed = true;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 0ec0bf0..e9ce1a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -19,6 +19,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.keyguard.clock.BubbleClockController;
+import com.android.keyguard.clock.StretchAnalogClockController;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.statusbar.StatusBarState;
@@ -146,6 +147,12 @@
                                 Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
                                 BubbleClockController.class.getName(),
                                 () -> BubbleClockController.build(mLayoutInflater)))
+                .withDefault(
+                        new SettingsGattedSupplier(
+                                mContentResolver,
+                                Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+                                StretchAnalogClockController.class.getName(),
+                                () -> StretchAnalogClockController.build(mLayoutInflater)))
                 .build();
         mContentResolver.registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
@@ -241,10 +248,6 @@
         mClockView.setShowCurrentUserTime(showCurrentUserTime);
     }
 
-    public void setElegantTextHeight(boolean elegant) {
-        mClockView.setElegantTextHeight(elegant);
-    }
-
     public void setTextSize(int unit, float size) {
         mClockView.setTextSize(unit, size);
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 41afa9a..3296c10 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -81,6 +81,11 @@
     protected void resetState() {
         mSecurityMessageDisplay.setMessage("");
         final boolean wasDisabled = mPasswordEntry.isEnabled();
+        // Don't set enabled password entry & showSoftInput when PasswordEntry is invisible or in
+        // pausing stage.
+        if (!mResumed || !mPasswordEntry.isVisibleToUser()) {
+            return;
+        }
         setPasswordEntryEnabled(true);
         setPasswordEntryInputEnabled(true);
         if (wasDisabled) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index f0cdc89..7ae4c41 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -202,10 +202,6 @@
         updateOwnerInfo();
         updateLogoutView();
         updateDark();
-
-        // Disable elegant text height because our fancy colon makes the ymin value huge for no
-        // reason.
-        mClockView.setElegantTextHeight(false);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
new file mode 100644
index 0000000..87347545
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard.clock;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Analog clock where the minute hand extends off of the screen.
+ */
+public class StretchAnalogClock extends View {
+
+    private static final int DEFAULT_COLOR = Color.parseColor("#F5C983");
+    private static final float HOUR_STROKE_WIDTH = 60f;
+    private static final float MINUTE_STROKE_WIDTH = 20f;
+    private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 80f;
+
+    private final Paint mHourPaint = new Paint();
+    private final Paint mMinutePaint = new Paint();
+    private Calendar mTime;
+    private TimeZone mTimeZone;
+
+    public StretchAnalogClock(Context context) {
+        this(context, null);
+    }
+
+    public StretchAnalogClock(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        init();
+    }
+
+    /**
+     * Call when the time changes to update the clock hands.
+     */
+    public void onTimeChanged() {
+        mTime.setTimeInMillis(System.currentTimeMillis());
+        invalidate();
+    }
+
+    /**
+     * Call when the time zone has changed to update clock hands.
+     *
+     * @param timeZone The updated time zone that will be used.
+     */
+    public void onTimeZoneChanged(TimeZone timeZone) {
+        mTime.setTimeZone(timeZone);
+    }
+
+    /**
+     * Set the color of the minute hand.
+     */
+    public void setMinuteHandColor(int color) {
+        mMinutePaint.setColor(color);
+        invalidate();
+    }
+
+    private void init() {
+        mHourPaint.setColor(DEFAULT_COLOR);
+        mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
+        mHourPaint.setAntiAlias(true);
+        mHourPaint.setStrokeCap(Paint.Cap.ROUND);
+
+        mMinutePaint.setColor(Color.WHITE);
+        mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
+        mMinutePaint.setAntiAlias(true);
+        mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        final float centerX = getWidth() / 2f;
+        final float centerY = getHeight() / 2f;
+
+        final float minutesRotation = mTime.get(Calendar.MINUTE) * 6f;
+        final float hoursRotation = (mTime.get(Calendar.HOUR) * 30);
+
+        // Compute length of clock hands. Hour hand is 60% the length from center to edge
+        // and minute hand is twice the length to make sure it extends past screen edge.
+        double sMinuteHandLengthFactor = Math.sin(2d * Math.PI * minutesRotation / 360d);
+        float sMinuteHandLength = (float) (2d * (centerY + (centerX - centerY)
+                * sMinuteHandLengthFactor * sMinuteHandLengthFactor));
+        double sHourHandLengthFactor = Math.sin(2d * Math.PI * hoursRotation / 360d);
+        float sHourHandLength = (float) (0.6d * (centerY + (centerX - centerY)
+                * sHourHandLengthFactor * sHourHandLengthFactor));
+
+        canvas.save();
+
+        canvas.rotate(minutesRotation, centerX, centerY);
+        canvas.drawLine(
+                centerX,
+                centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
+                centerX,
+                centerY - sMinuteHandLength,
+                mMinutePaint);
+
+        canvas.rotate(hoursRotation - minutesRotation, centerX, centerY);
+        canvas.drawLine(
+                centerX,
+                centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
+                centerX,
+                centerY - sHourHandLength,
+                mHourPaint);
+
+        canvas.restore();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+        onTimeChanged();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
new file mode 100644
index 0000000..0a39158
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClockController.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard.clock;
+
+import android.graphics.Paint.Style;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextClock;
+
+import com.android.keyguard.R;
+import com.android.systemui.plugins.ClockPlugin;
+
+import java.util.TimeZone;
+
+/**
+ * Controller for Stretch clock that can appear on lock screen and AOD.
+ */
+public class StretchAnalogClockController implements ClockPlugin {
+
+    /**
+     * Custom clock shown on AOD screen and behind stack scroller on lock.
+     */
+    private View mBigClockView;
+    private TextClock mDigitalClock;
+    private StretchAnalogClock mAnalogClock;
+
+    /**
+     * Small clock shown on lock screen above stack scroller.
+     */
+    private View mView;
+    private TextClock mLockClock;
+
+    /**
+     * Controller for transition to dark state.
+     */
+    private CrossFadeDarkController mDarkController;
+
+    private StretchAnalogClockController() { }
+
+    /**
+     * Create a BubbleClockController instance.
+     *
+     * @param layoutInflater Inflater used to inflate custom clock views.
+     */
+    public static StretchAnalogClockController build(LayoutInflater layoutInflater) {
+        StretchAnalogClockController controller = new StretchAnalogClockController();
+        controller.createViews(layoutInflater);
+        return controller;
+    }
+
+    private void createViews(LayoutInflater layoutInflater) {
+        mBigClockView = layoutInflater.inflate(R.layout.stretchanalog_clock, null);
+        mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
+        mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
+
+        mView = layoutInflater.inflate(R.layout.digital_clock, null);
+        mLockClock = mView.findViewById(R.id.lock_screen_clock);
+        mLockClock.setVisibility(View.GONE);
+
+        mDarkController = new CrossFadeDarkController(mDigitalClock, mLockClock);
+    }
+
+    @Override
+    public View getView() {
+        return mView;
+    }
+
+    @Override
+    public View getBigClockView() {
+        return mBigClockView;
+    }
+
+    @Override
+    public void setStyle(Style style) {}
+
+    @Override
+    public void setTextColor(int color) {
+        mLockClock.setTextColor(color);
+        mDigitalClock.setTextColor(color);
+        mAnalogClock.setMinuteHandColor(color);
+    }
+
+    @Override
+    public void dozeTimeTick() {
+        mAnalogClock.onTimeChanged();
+    }
+
+    @Override
+    public void setDarkAmount(float darkAmount) {
+        mDarkController.setDarkAmount(darkAmount);
+    }
+
+    @Override
+    public void onTimeZoneChanged(TimeZone timeZone) {
+        mAnalogClock.onTimeZoneChanged(timeZone);
+    }
+
+    @Override
+    public boolean shouldShowStatusArea() {
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 16e869e..e28aa9d 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -37,23 +37,25 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.leak.RotationUtils;
 
-public class HardwareUiLayout extends LinearLayout implements Tunable {
+/**
+ * Layout for placing two containers at a specific physical position on the device, relative to the
+ * device's hardware, regardless of screen rotation.
+ */
+public class HardwareUiLayout extends MultiListLayout implements Tunable {
 
     private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
     private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
     private final int[] mTmp2 = new int[2];
-    private View mList;
-    private View mSeparatedView;
+    private ViewGroup mList;
+    private ViewGroup mSeparatedView;
     private int mOldHeight;
     private boolean mAnimating;
     private AnimatorSet mAnimation;
     private View mDivision;
-    private boolean mHasOutsideTouch;
     private HardwareBgDrawable mListBackground;
     private HardwareBgDrawable mSeparatedViewBackground;
     private Animator mAnimator;
     private boolean mCollapse;
-    private boolean mHasSeparatedButton;
     private int mEndPoint;
     private boolean mEdgeBleed;
     private boolean mRoundedDivider;
@@ -67,6 +69,35 @@
     }
 
     @Override
+    protected ViewGroup getSeparatedView() {
+        return findViewById(com.android.systemui.R.id.separated_button);
+    }
+
+    @Override
+    protected ViewGroup getListView() {
+        return findViewById(android.R.id.list);
+    }
+
+    @Override
+    public void removeAllItems() {
+        if (mList != null) {
+            mList.removeAllViews();
+        }
+        if (mSeparatedView != null) {
+            mSeparatedView.removeAllViews();
+        }
+    }
+
+    @Override
+    public ViewGroup getParentView(boolean separated, int index) {
+        if (separated) {
+            return getSeparatedView();
+        } else {
+            return getListView();
+        }
+    }
+
+    @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         updateSettings();
@@ -137,9 +168,9 @@
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         if (mList == null) {
             if (getChildCount() != 0) {
-                mList = getChildAt(0);
+                mList = getListView();
                 mList.setBackground(mListBackground);
-                mSeparatedView = getChildAt(1);
+                mSeparatedView = getSeparatedView();
                 mSeparatedView.setBackground(mSeparatedViewBackground);
                 updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
                 mOldHeight = mList.getMeasuredHeight();
@@ -187,7 +218,7 @@
         } else {
             rotateLeft();
         }
-        if (mHasSeparatedButton) {
+        if (mHasSeparatedView) {
             if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) {
                 // Separated view has top margin, so seascape separated view need special rotation,
                 // not a full left or right rotation.
@@ -408,8 +439,8 @@
         if (mList == null) return;
         // If got separated button, setRotatedBackground to false,
         // all items won't get white background.
-        mListBackground.setRotatedBackground(mHasSeparatedButton);
-        mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton);
+        mListBackground.setRotatedBackground(mHasSeparatedView);
+        mSeparatedViewBackground.setRotatedBackground(mHasSeparatedView);
         if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
             int index = mRotatedBackground ? 0 : 1;
             mDivision.getLocationOnScreen(mTmp2);
@@ -460,21 +491,21 @@
             case RotationUtils.ROTATION_LANDSCAPE:
                 defaultTopPadding = getPaddingLeft();
                 viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
-                separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
+                separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
                 screenHeight = getMeasuredWidth();
                 targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP;
                 break;
             case RotationUtils.ROTATION_SEASCAPE:
                 defaultTopPadding = getPaddingRight();
                 viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth();
-                separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0;
+                separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0;
                 screenHeight = getMeasuredWidth();
                 targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM;
                 break;
             default: // Portrait
                 defaultTopPadding = getPaddingTop();
                 viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight();
-                separatedViewTopMargin = mHasSeparatedButton ? params.topMargin : 0;
+                separatedViewTopMargin = mHasSeparatedView ? params.topMargin : 0;
                 screenHeight = getMeasuredHeight();
                 targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT;
                 break;
@@ -491,30 +522,10 @@
         return super.getOutlineProvider();
     }
 
-    public void setOutsideTouchListener(OnClickListener onClickListener) {
-        mHasOutsideTouch = true;
-        requestLayout();
-        setOnClickListener(onClickListener);
-        setClickable(true);
-        setFocusable(true);
-    }
-
     public void setCollapse() {
         mCollapse = true;
     }
 
-    public void setHasSeparatedButton(boolean hasSeparatedButton) {
-        mHasSeparatedButton = hasSeparatedButton;
-    }
-
-    public static HardwareUiLayout get(View v) {
-        if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v;
-        if (v.getParent() instanceof View) {
-            return get((View) v.getParent());
-        }
-        return null;
-    }
-
     private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> {
         if (mHasOutsideTouch || (mList == null)) {
             inoutInfo.setTouchableInsets(
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
new file mode 100644
index 0000000..0c7a9a9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * Layout class representing the Global Actions menu which appears when the power button is held.
+ */
+public abstract class MultiListLayout extends LinearLayout {
+    boolean mHasOutsideTouch;
+    boolean mHasSeparatedView;
+
+    int mExpectedSeparatedItemCount;
+    int mExpectedListItemCount;
+
+    public MultiListLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    protected abstract ViewGroup getSeparatedView();
+
+    protected abstract ViewGroup getListView();
+
+    /**
+     * Removes all child items from the separated and list views, if they exist.
+     */
+    public abstract void removeAllItems();
+
+    /**
+     * Get the parent view which will be used to contain the item at the specified index.
+     * @param separated Whether or not this index refers to a position in the separated or list
+     *                  container.
+     * @param index The index of the item within the container.
+     * @return The parent ViewGroup which will be used to contain the specified item
+     * after it has been added to the layout.
+     */
+    public abstract ViewGroup getParentView(boolean separated, int index);
+
+    /**
+     * Sets the divided view, which may have a differently-colored background.
+     */
+    public abstract void setDivisionView(View v);
+
+    /**
+     * Set the view accessibility delegate for the list view container.
+     */
+    public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) {
+        getListView().setAccessibilityDelegate(delegate);
+    }
+
+    protected void setSeparatedViewVisibility(boolean visible) {
+        getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    /**
+     * Sets the number of items expected to be rendered in the separated container. This allows the
+     * layout to correctly determine which parent containers will be used for items before they have
+     * beenadded to the layout.
+     * @param count The number of items expected.
+     */
+    public void setExpectedSeparatedItemCount(int count) {
+        mExpectedSeparatedItemCount = count;
+    }
+
+    /**
+     * Sets the number of items expected to be rendered in the list container. This allows the
+     * layout to correctly determine which parent containers will be used for items before they have
+     * beenadded to the layout.
+     * @param count The number of items expected.
+     */
+    public void setExpectedListItemCount(int count) {
+        mExpectedListItemCount = count;
+    }
+
+    /**
+     * Sets whether the separated view should be shown, and handles updating visibility on
+     * that view.
+     */
+    public void setHasSeparatedView(boolean hasSeparatedView) {
+        mHasSeparatedView = hasSeparatedView;
+        setSeparatedViewVisibility(hasSeparatedView);
+    }
+
+    /**
+     * Sets this layout to respond to an outside touch listener.
+     */
+    public void setOutsideTouchListener(OnClickListener onClickListener) {
+        mHasOutsideTouch = true;
+        requestLayout();
+        setOnClickListener(onClickListener);
+        setClickable(true);
+        setFocusable(true);
+    }
+
+    /**
+     * Retrieve the MultiListLayout associated with the given view.
+     */
+    public static MultiListLayout get(View v) {
+        if (v instanceof MultiListLayout) return (MultiListLayout) v;
+        if (v.getParent() instanceof View) {
+            return get((View) v.getParent());
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 4cb1fee..bd7a421 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -38,7 +38,13 @@
     void setAnimateWakeup(boolean animateWakeup);
     void setAnimateScreenOff(boolean animateScreenOff);
 
-    void onDoubleTap(float x, float y);
+    /**
+     * Reports that a tap event happend on the Sensors Low Power Island.
+     *
+     * @param x Touch X, or -1 if sensor doesn't support touch location.
+     * @param y Touch Y, or -1 if sensor doesn't support touch location.
+     */
+    void onSlpiTap(float x, float y);
 
     default void setAodDimmingScrim(float scrimOpacity) {}
     void setDozeScreenBrightness(int value);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 50003e3..a784773 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -35,7 +35,7 @@
     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
     static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
-    private static final int REASONS = 9;
+    private static final int REASONS = 10;
 
     public static final int PULSE_REASON_NONE = -1;
     public static final int PULSE_REASON_INTENT = 0;
@@ -47,6 +47,7 @@
     public static final int PULSE_REASON_DOCKING = 6;
     public static final int REASON_SENSOR_WAKE_UP = 7;
     public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8;
+    public static final int PULSE_REASON_SENSOR_TAP = 9;
 
     private static boolean sRegisterKeyguardCallback = true;
 
@@ -207,6 +208,7 @@
             case PULSE_REASON_DOCKING: return "docking";
             case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen";
             case REASON_SENSOR_WAKE_UP: return "wakeup";
+            case PULSE_REASON_SENSOR_TAP: return "tap";
             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index b6fc355..78374a0 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -107,6 +107,13 @@
                         dozeParameters.doubleTapReportsTouchCoordinates(),
                         true /* touchscreen */),
                 new TriggerSensor(
+                        findSensorWithType(config.tapSensorType()),
+                        Settings.Secure.DOZE_TAP_SCREEN_GESTURE,
+                        true /* configured */,
+                        DozeLog.PULSE_REASON_SENSOR_TAP,
+                        false /* reports touch coordinates */,
+                        true /* touchscreen */),
+                new TriggerSensor(
                         findSensorWithType(config.longPressSensorType()),
                         Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
                         false /* settingDef */,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 6a9b689..e2e448b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -132,6 +132,7 @@
     private void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
             float screenX, float screenY, float[] rawValues) {
         boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
+        boolean isTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_TAP;
         boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
         boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
         boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP;
@@ -148,8 +149,10 @@
                     // In pocket, drop event.
                     return;
                 }
-                if (isDoubleTap) {
-                    mDozeHost.onDoubleTap(screenX, screenY);
+                if (isDoubleTap || isTap) {
+                    if (screenX != -1 && screenY != -1) {
+                        mDozeHost.onSlpiTap(screenX, screenY);
+                    }
                     mMachine.wakeUp();
                 } else if (isPickup) {
                     mMachine.wakeUp();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 268245b..7b18fad 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -67,10 +67,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.internal.R;
@@ -86,8 +84,8 @@
 import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.Dependency;
-import com.android.systemui.HardwareUiLayout;
 import com.android.systemui.Interpolators;
+import com.android.systemui.MultiListLayout;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -490,6 +488,11 @@
         public boolean showBeforeProvisioning() {
             return true;
         }
+
+        @Override
+        public boolean shouldBeSeparated() {
+            return true;
+        }
     }
 
     private final class RestartAction extends SinglePressAction implements LongPressAction {
@@ -926,6 +929,34 @@
             return getItem(position).isEnabled();
         }
 
+        public ArrayList<Action> getSeparatedActions(boolean shouldUseSeparatedView) {
+            ArrayList<Action> separatedActions = new ArrayList<Action>();
+            if (!shouldUseSeparatedView) {
+                return separatedActions;
+            }
+            for (int i = 0; i < mItems.size(); i++) {
+                final Action action = mItems.get(i);
+                if (action.shouldBeSeparated()) {
+                    separatedActions.add(action);
+                }
+            }
+            return separatedActions;
+        }
+
+        public ArrayList<Action> getListActions(boolean shouldUseSeparatedView) {
+            if (!shouldUseSeparatedView) {
+                return new ArrayList<Action>(mItems);
+            }
+            ArrayList<Action> listActions = new ArrayList<Action>();
+            for (int i = 0; i < mItems.size(); i++) {
+                final Action action = mItems.get(i);
+                if (!action.shouldBeSeparated()) {
+                    listActions.add(action);
+                }
+            }
+            return listActions;
+        }
+
         @Override
         public boolean areAllItemsEnabled() {
             return false;
@@ -965,7 +996,7 @@
             View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext));
             // Everything but screenshot, the last item, gets white background.
             if (position == getCount() - 1) {
-                HardwareUiLayout.get(parent).setDivisionView(view);
+                MultiListLayout.get(parent).setDivisionView(view);
             }
             return view;
         }
@@ -1004,6 +1035,10 @@
         boolean showBeforeProvisioning();
 
         boolean isEnabled();
+
+        default boolean shouldBeSeparated() {
+            return false;
+        }
     }
 
     /**
@@ -1423,9 +1458,7 @@
 
         private final Context mContext;
         private final MyAdapter mAdapter;
-        private final LinearLayout mListView;
-        private final FrameLayout mSeparatedView;
-        private final HardwareUiLayout mHardwareLayout;
+        private final MultiListLayout mGlobalActionsLayout;
         private final OnClickListener mClickListener;
         private final OnItemLongClickListener mLongClickListener;
         private final GradientDrawable mGradientDrawable;
@@ -1466,16 +1499,11 @@
             window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
 
             setContentView(com.android.systemui.R.layout.global_actions_wrapped);
-            mListView = findViewById(android.R.id.list);
-            mSeparatedView = findViewById(com.android.systemui.R.id.separated_button);
-            if (!mShouldDisplaySeparatedButton) {
-                mSeparatedView.setVisibility(View.GONE);
-            }
-            mHardwareLayout = HardwareUiLayout.get(mListView);
-            mHardwareLayout.setOutsideTouchListener(view -> dismiss());
-            mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton);
-            setTitle(R.string.global_actions);
-            mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+            mGlobalActionsLayout = (MultiListLayout)
+                    findViewById(com.android.systemui.R.id.global_actions_view);
+            mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
+            mGlobalActionsLayout.setHasSeparatedView(mShouldDisplaySeparatedButton);
+            mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {
                 @Override
                 public boolean dispatchPopulateAccessibilityEvent(
                         View host, AccessibilityEvent event) {
@@ -1484,20 +1512,33 @@
                     return true;
                 }
             });
+            setTitle(R.string.global_actions);
         }
 
         private void updateList() {
-            mListView.removeAllViews();
-            mSeparatedView.removeAllViews();
+            mGlobalActionsLayout.removeAllItems();
+            ArrayList<Action> separatedActions =
+                    mAdapter.getSeparatedActions(mShouldDisplaySeparatedButton);
+            ArrayList<Action> listActions = mAdapter.getListActions(mShouldDisplaySeparatedButton);
+            mGlobalActionsLayout.setExpectedListItemCount(listActions.size());
+            mGlobalActionsLayout.setExpectedSeparatedItemCount(separatedActions.size());
+
             for (int i = 0; i < mAdapter.getCount(); i++) {
-                ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1
-                        ? mSeparatedView : mListView;
-                View v = mAdapter.getView(i, null, parentView);
+                Action action = mAdapter.getItem(i);
+                int separatedIndex = separatedActions.indexOf(action);
+                ViewGroup parent;
+                if (separatedIndex != -1) {
+                    parent = mGlobalActionsLayout.getParentView(true, separatedIndex);
+                } else {
+                    int listIndex = listActions.indexOf(action);
+                    parent = mGlobalActionsLayout.getParentView(false, listIndex);
+                }
+                View v = mAdapter.getView(i, null, parent);
                 final int pos = i;
                 v.setOnClickListener(view -> mClickListener.onClick(this, pos));
                 v.setOnLongClickListener(view ->
                         mLongClickListener.onItemLongClick(null, v, pos, 0));
-                parentView.addView(v);
+                parent.addView(v);
             }
         }
 
@@ -1543,9 +1584,9 @@
             super.show();
             mShowing = true;
             mGradientDrawable.setAlpha(0);
-            mHardwareLayout.setTranslationX(getAnimTranslation());
-            mHardwareLayout.setAlpha(0);
-            mHardwareLayout.animate()
+            mGlobalActionsLayout.setTranslationX(getAnimTranslation());
+            mGlobalActionsLayout.setAlpha(0);
+            mGlobalActionsLayout.animate()
                     .alpha(1)
                     .translationX(0)
                     .setDuration(300)
@@ -1564,9 +1605,9 @@
                 return;
             }
             mShowing = false;
-            mHardwareLayout.setTranslationX(0);
-            mHardwareLayout.setAlpha(1);
-            mHardwareLayout.animate()
+            mGlobalActionsLayout.setTranslationX(0);
+            mGlobalActionsLayout.setAlpha(1);
+            mGlobalActionsLayout.animate()
                     .alpha(0)
                     .translationX(getAnimTranslation())
                     .setDuration(300)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
index 5230cea..7ee37d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java
@@ -84,7 +84,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return null;
+        return new Intent();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index eea4490..839b06c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -33,6 +33,13 @@
     default void onPendingEntryAdded(NotificationEntry entry) {
     }
 
+    // TODO: Combine this with onPreEntryUpdated into "onBeforeEntryFiltered" or similar
+    /**
+     * Called when a new entry is created but before it has been filtered or displayed to the user.
+     */
+    default void onBeforeNotificationAdded(NotificationEntry entry) {
+    }
+
     /**
      * Called when a new entry is created.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 45db002..989e781 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -18,11 +18,9 @@
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.content.Context;
-import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -41,7 +39,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationInflater;
 import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.leak.LeakDetector;
 
@@ -68,8 +65,6 @@
     @VisibleForTesting
     protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
 
-    private final DeviceProvisionedController mDeviceProvisionedController =
-            Dependency.get(DeviceProvisionedController.class);
     private final ForegroundServiceController mForegroundServiceController =
             Dependency.get(ForegroundServiceController.class);
 
@@ -81,25 +76,12 @@
     private NotificationListenerService.RankingMap mLatestRankingMap;
     @VisibleForTesting
     protected NotificationData mNotificationData;
-    private NotificationListContainer mListContainer;
+
     @VisibleForTesting
     final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
             = new ArrayList<>();
     private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
 
-    private final DeviceProvisionedController.DeviceProvisionedListener
-            mDeviceProvisionedListener =
-            new DeviceProvisionedController.DeviceProvisionedListener() {
-                @Override
-                public void onDeviceProvisionedChanged() {
-                    updateNotifications();
-                }
-            };
-
-    public void destroy() {
-        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
-    }
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationEntryManager state:");
@@ -151,9 +133,6 @@
             HeadsUpManager headsUpManager) {
         mPresenter = presenter;
         mNotificationData.setHeadsUpManager(headsUpManager);
-        mListContainer = listContainer;
-
-        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
     }
 
     /** Adds multiple {@link NotificationLifetimeExtender}s. */
@@ -227,7 +206,9 @@
                     listener.onEntryInflated(entry, inflatedFlags);
                 }
                 mNotificationData.add(entry);
-                tagForeground(entry.notification);
+                for (NotificationEntryListener listener : mNotificationEntryListeners) {
+                    listener.onBeforeNotificationAdded(entry);
+                }
                 updateNotifications();
                 for (NotificationEntryListener listener : mNotificationEntryListeners) {
                     listener.onNotificationAdded(entry);
@@ -283,7 +264,6 @@
 
                 if (entry.rowExists()) {
                     entry.removeRow();
-                    mListContainer.cleanUpViewStateForEntry(entry);
                 }
 
                 // Let's remove the children if this was a summary
@@ -368,19 +348,6 @@
         }
     }
 
-    @VisibleForTesting
-    void tagForeground(StatusBarNotification notification) {
-        ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
-                notification.getUserId(), notification.getPackageName());
-        if (activeOps != null) {
-            int N = activeOps.size();
-            for (int i = 0; i < N; i++) {
-                updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
-                        notification.getPackageName(), true);
-            }
-        }
-    }
-
     @Override
     public void addNotification(StatusBarNotification notification,
             NotificationListenerService.RankingMap ranking) {
@@ -391,15 +358,6 @@
         }
     }
 
-    public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
-        String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
-                UserHandle.getUserId(uid), pkg);
-        if (foregroundKey != null) {
-            mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
-            updateNotifications();
-        }
-    }
-
     private void updateNotificationInternal(StatusBarNotification notification,
             NotificationListenerService.RankingMap ranking) throws InflationException {
         if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
@@ -452,8 +410,9 @@
 
     public void updateNotifications() {
         mNotificationData.filterAndSort();
-
-        mPresenter.updateNotificationViews();
+        if (mPresenter != null) {
+            mPresenter.updateNotificationViews();
+        }
     }
 
     public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
new file mode 100644
index 0000000..88f4ca2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
+/**
+ * Root controller for the list of notifications in the shade.
+ *
+ * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
+ * domain-specific behavior (ARC, etc) to subcontrollers.
+ */
+public class NotificationListController {
+    private final NotificationEntryManager mEntryManager;
+    private final NotificationListContainer mListContainer;
+    private final ForegroundServiceController mForegroundServiceController;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+
+    public NotificationListController(
+            NotificationEntryManager entryManager,
+            NotificationListContainer listContainer,
+            ForegroundServiceController foregroundServiceController,
+            DeviceProvisionedController deviceProvisionedController) {
+        mEntryManager = checkNotNull(entryManager);
+        mListContainer = checkNotNull(listContainer);
+        mForegroundServiceController = checkNotNull(foregroundServiceController);
+        mDeviceProvisionedController = checkNotNull(deviceProvisionedController);
+    }
+
+    /**
+     * Causes the controller to register listeners on its dependencies. This method must be called
+     * before the controller is ready to perform its duties.
+     */
+    public void bind() {
+        mEntryManager.addNotificationEntryListener(mEntryListener);
+        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+    }
+
+    /** Should be called when the list controller is being destroyed. */
+    public void destroy() {
+        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
+    }
+
+    @SuppressWarnings("FieldCanBeLocal")
+    private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
+        @Override
+        public void onEntryRemoved(
+                NotificationEntry entry,
+                NotificationVisibility visibility,
+                boolean removedByUser) {
+            mListContainer.cleanUpViewStateForEntry(entry);
+        }
+
+        @Override
+        public void onBeforeNotificationAdded(NotificationEntry entry) {
+            tagForeground(entry.notification);
+        }
+    };
+
+    private final DeviceProvisionedListener mDeviceProvisionedListener =
+            new DeviceProvisionedListener() {
+                @Override
+                public void onDeviceProvisionedChanged() {
+                    mEntryManager.updateNotifications();
+                }
+            };
+
+    // TODO: This method is horrifically inefficient
+    private void tagForeground(StatusBarNotification notification) {
+        ArraySet<Integer> activeOps =
+                mForegroundServiceController.getAppOps(
+                        notification.getUserId(), notification.getPackageName());
+        if (activeOps != null) {
+            int len = activeOps.size();
+            for (int i = 0; i < len; i++) {
+                updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
+                        notification.getPackageName(), true);
+            }
+        }
+    }
+
+    /** When an app op changes, propagate that change to notifications. */
+    public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
+        String foregroundKey =
+                mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg);
+        if (foregroundKey != null) {
+            mEntryManager
+                    .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
+            mEntryManager.updateNotifications();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 31310f5..32cc0e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -141,6 +141,7 @@
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     private KeyguardStatusBarView mKeyguardStatusBar;
+    private ViewGroup mBigClockContainer;
     private QS mQs;
     private FrameLayout mQsFrame;
     @VisibleForTesting
@@ -348,8 +349,8 @@
         mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
 
         KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
-        ViewGroup bigClockContainer = findViewById(R.id.big_clock_container);
-        keyguardClockSwitch.setBigClockContainer(bigClockContainer);
+        mBigClockContainer = findViewById(R.id.big_clock_container);
+        keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
 
         mNotificationContainerParent = findViewById(R.id.notification_container_parent);
         mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
@@ -585,6 +586,11 @@
                     mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
             PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
                     mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
+            // Move big clock up while pulling up the bouncer
+            PropertyAnimator.setProperty(mBigClockContainer, AnimatableProperty.Y,
+                    MathUtils.lerp(-mBigClockContainer.getHeight(), 0,
+                          Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(getExpandedFraction())),
+                    CLOCK_ANIMATION_PROPERTIES, animateClock);
             updateClock();
             stackScrollerPadding = mClockPositionResult.stackScrollerPadding;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 853d7ab..3568f28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -612,9 +612,11 @@
         anim.setStartDelay(mAnimationDelay);
         anim.setDuration(mAnimationDuration);
         anim.addListener(new AnimatorListenerAdapter() {
+            private Callback lastCallback = mCallback;
+
             @Override
             public void onAnimationEnd(Animator animation) {
-                onFinished();
+                onFinished(lastCallback);
 
                 scrim.setTag(TAG_KEY_ANIM, null);
                 dispatchScrimsVisible();
@@ -672,14 +674,23 @@
     }
 
     private void onFinished() {
+        onFinished(mCallback);
+    }
+
+    private void onFinished(Callback callback) {
         if (mWakeLockHeld) {
             mWakeLock.release();
             mWakeLockHeld = false;
         }
-        if (mCallback != null) {
-            mCallback.onFinished();
-            mCallback = null;
+
+        if (callback != null) {
+            callback.onFinished();
+
+            if (callback == mCallback) {
+                mCallback = null;
+            }
         }
+
         // When unlocking with fingerprint, we'll fade the scrims from black to transparent.
         // At the end of the animation we need to remove the tint.
         if (mState == ScrimState.UNLOCKED) {
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 514bb22..ed71598 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -196,6 +196,7 @@
 import com.android.systemui.statusbar.notification.NotificationClicker;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationListController;
 import com.android.systemui.statusbar.notification.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -387,6 +388,7 @@
     private NotificationGutsManager mGutsManager;
     protected NotificationLogger mNotificationLogger;
     protected NotificationEntryManager mEntryManager;
+    private NotificationListController mNotificationListController;
     private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
     private NotificationRowBinder mNotificationRowBinder;
     protected NotificationViewHierarchyManager mViewHierarchyManager;
@@ -593,7 +595,7 @@
     public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
         mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
         Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
-            mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
+            mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
         });
     }
 
@@ -1044,6 +1046,13 @@
                 mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
                 mNotificationAlertingManager);
 
+        mNotificationListController =
+                new NotificationListController(
+                        mEntryManager,
+                        (NotificationListContainer) mStackScroller,
+                        mForegroundServiceController,
+                        mDeviceProvisionedController);
+
         mAppOpsController.addCallback(APP_OPS, this);
         mNotificationListener.setUpWithPresenter(mPresenter);
         mNotificationShelf.setOnActivatedListener(mPresenter);
@@ -1056,6 +1065,7 @@
                 this, Dependency.get(BubbleController.class), mNotificationActivityStarter));
 
         mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
+        mNotificationListController.bind();
     }
 
     /**
@@ -2831,7 +2841,7 @@
         } catch (RemoteException e) {
             // Ignore.
         }
-        mEntryManager.destroy();
+        mNotificationListController.destroy();
         // End old BaseStatusBar.destroy().
         if (mStatusBarWindow != null) {
             mWindowManager.removeViewImmediate(mStatusBarWindow);
@@ -3999,7 +4009,7 @@
         }
 
         @Override
-        public void onDoubleTap(float screenX, float screenY) {
+        public void onSlpiTap(float screenX, float screenY) {
             if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null
                 && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) {
                 mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2);
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 9422101..f79ad71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -541,7 +541,8 @@
 
     @VisibleForTesting
     void doUpdateMobileControllers() {
-        List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList();
+        List<SubscriptionInfo> subscriptions = mSubscriptionManager
+                .getActiveSubscriptionInfoList(true);
         if (subscriptions == null) {
             subscriptions = Collections.emptyList();
         }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
new file mode 100644
index 0000000..8de8f3d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/StretchAnalogClockControllerTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard.clock;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public final class StretchAnalogClockControllerTest extends SysuiTestCase {
+
+    private StretchAnalogClockController mClockController;
+
+    @Before
+    public void setUp() {
+        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
+        mClockController = StretchAnalogClockController.build(layoutInflater);
+    }
+
+    @Test
+    public void setDarkAmount_fadeIn() {
+        ViewGroup smallClockFrame = (ViewGroup) mClockController.getView();
+        View smallClock = smallClockFrame.getChildAt(0);
+        // WHEN dark amount is set to AOD
+        mClockController.setDarkAmount(1f);
+        // THEN small clock should not be shown.
+        assertThat(smallClock.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void setTextColor_setDigitalClock() {
+        ViewGroup smallClock = (ViewGroup) mClockController.getView();
+        // WHEN text color is set
+        mClockController.setTextColor(42);
+        // THEN child of small clock should have text color set.
+        TextView digitalClock = (TextView) smallClock.getChildAt(0);
+        assertThat(digitalClock.getCurrentTextColor()).isEqualTo(42);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
index ce28b50..dc42872 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
@@ -104,7 +104,7 @@
     }
 
     @Override
-    public void onDoubleTap(float x, float y) {
+    public void onSlpiTap(float x, float y) {
         doubleTapX = y;
         doubleTapY = y;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index d937f93..9ce6ae1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -22,19 +22,15 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
-import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -49,7 +45,6 @@
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.ArraySet;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -79,8 +74,6 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
-import junit.framework.Assert;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -346,7 +339,6 @@
 
         verify(mEntryListener, never()).onInflationError(any(), any());
 
-        verify(mListContainer).cleanUpViewStateForEntry(mEntry);
         verify(mPresenter).updateNotificationViews();
         verify(mEntryListener).onEntryRemoved(
                 mEntry, null, false /* removedByUser */);
@@ -401,90 +393,6 @@
     }
 
     @Test
-    public void testUpdateAppOps_foregroundNoti() {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(mEntry.key);
-        mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
-
-        mEntryManager.updateNotificationsForAppOp(
-                AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
-                mEntry.notification.getPackageName(), true);
-
-        verify(mPresenter, times(1)).updateNotificationViews();
-        assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains(
-                AppOpsManager.OP_CAMERA));
-    }
-
-    @Test
-    public void testUpdateAppOps_otherNoti() {
-        com.android.systemui.util.Assert.isNotMainThread();
-
-        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
-                .thenReturn(null);
-        mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
-
-        verify(mPresenter, never()).updateNotificationViews();
-    }
-
-    @Test
-    public void testAddNotificationExistingAppOps() {
-        mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
-        ArraySet<Integer> expected = new ArraySet<>();
-        expected.add(3);
-        expected.add(235);
-        expected.add(1);
-
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(expected);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
-
-        mEntryManager.tagForeground(mEntry.notification);
-
-        Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
-        for (int op : expected) {
-            assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
-        }
-    }
-
-    @Test
-    public void testAdd_noExistingAppOps() {
-        mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(mEntry.key);
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(null);
-
-        mEntryManager.tagForeground(mEntry.notification);
-        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
-    }
-
-    @Test
-    public void testAdd_existingAppOpsNotForegroundNoti() {
-        mEntry.setRow(mRow);
-        mEntryManager.getNotificationData().add(mEntry);
-        ArraySet<Integer> ops = new ArraySet<>();
-        ops.add(3);
-        ops.add(235);
-        ops.add(1);
-        when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn(ops);
-        when(mForegroundServiceController.getStandardLayoutKey(
-                mEntry.notification.getUserId(),
-                mEntry.notification.getPackageName())).thenReturn("something else");
-
-        mEntryManager.tagForeground(mEntry.notification);
-        Assert.assertEquals(0, mEntry.mActiveAppOps.size());
-    }
-
-    @Test
     public void testUpdateNotificationRanking() {
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
         when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
new file mode 100644
index 0000000..4b5037b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.ArraySet;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class NotificationListControllerTest extends SysuiTestCase {
+    private NotificationListController mController;
+
+    @Mock private NotificationEntryManager mEntryManager;
+    @Mock private NotificationListContainer mListContainer;
+    @Mock private ForegroundServiceController mForegroundServiceController;
+    @Mock private DeviceProvisionedController mDeviceProvisionedController;
+
+    @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
+    @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
+
+    private NotificationEntryListener mEntryListener;
+    private DeviceProvisionedListener mProvisionedListener;
+
+    // TODO: Remove this once EntryManager no longer needs to be mocked
+    private NotificationData mNotificationData = new NotificationData();
+
+    private int mNextNotifId = 0;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+
+        mController = new NotificationListController(
+                mEntryManager,
+                mListContainer,
+                mForegroundServiceController,
+                mDeviceProvisionedController);
+        mController.bind();
+
+        // Capture callbacks passed to mocks
+        verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
+        mEntryListener = mEntryListenerCaptor.getValue();
+        verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
+        mProvisionedListener = mProvisionedCaptor.getValue();
+    }
+
+    @Test
+    public void testCleanUpViewStateOnEntryRemoved() {
+        final NotificationEntry entry = buildEntry();
+        mEntryListener.onEntryRemoved(
+                entry,
+                NotificationVisibility.obtain(entry.key, 0, 0, true),
+                false);
+        verify(mListContainer).cleanUpViewStateForEntry(entry);
+    }
+
+    @Test
+    public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
+        mProvisionedListener.onDeviceProvisionedChanged();
+        verify(mEntryManager).updateNotifications();
+    }
+
+    @Test
+    public void testAppOps_appOpAddedToForegroundNotif() {
+        // GIVEN a notification associated with a foreground service
+        final NotificationEntry entry = buildEntry();
+        mNotificationData.add(entry);
+        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+                .thenReturn(entry.key);
+
+        // WHEN we are notified of a new app op
+        mController.updateNotificationsForAppOp(
+                AppOpsManager.OP_CAMERA,
+                entry.notification.getUid(),
+                entry.notification.getPackageName(),
+                true);
+
+        // THEN the app op is added to the entry
+        assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+        // THEN updateNotifications() is called
+        verify(mEntryManager, times(1)).updateNotifications();
+    }
+
+    @Test
+    public void testAppOps_appOpAddedToUnrelatedNotif() {
+        // GIVEN No current foreground notifs
+        when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
+                .thenReturn(null);
+
+        // WHEN An unrelated notification gets a new app op
+        mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
+
+        // THEN We never call updateNotifications()
+        verify(mEntryManager, never()).updateNotifications();
+    }
+
+    @Test
+    public void testAppOps_addNotificationWithExistingAppOps() {
+        // GIVEN a notification with three associated app ops that is associated with a foreground
+        // service
+        final NotificationEntry entry = buildEntry();
+        mNotificationData.add(entry);
+        ArraySet<Integer> expected = new ArraySet<>();
+        expected.add(3);
+        expected.add(235);
+        expected.add(1);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn(entry.key);
+        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn(expected);
+
+        // WHEN the notification is added
+        mEntryListener.onBeforeNotificationAdded(entry);
+
+        // THEN the entry is tagged with all three app ops
+        assertEquals(expected.size(), entry.mActiveAppOps.size());
+        for (int op : expected) {
+            assertTrue("Entry missing op " + op, entry.mActiveAppOps.contains(op));
+        }
+    }
+
+    @Test
+    public void testAdd_addNotificationWithNoExistingAppOps() {
+        // GIVEN a notification with NO associated app ops
+        final NotificationEntry entry = buildEntry();
+
+        mNotificationData.add(entry);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn(entry.key);
+        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn(null);
+
+        // WHEN the notification is added
+        mEntryListener.onBeforeNotificationAdded(entry);
+
+        // THEN the entry doesn't have any app ops associated with it
+        assertEquals(0, entry.mActiveAppOps.size());
+    }
+
+    @Test
+    public void testAdd_addNonForegroundNotificationWithExistingAppOps() {
+        // GIVEN a notification with app ops that isn't associated with a foreground service
+        final NotificationEntry entry = buildEntry();
+        mNotificationData.add(entry);
+        ArraySet<Integer> ops = new ArraySet<>();
+        ops.add(3);
+        ops.add(235);
+        ops.add(1);
+        when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn(ops);
+        when(mForegroundServiceController.getStandardLayoutKey(
+                entry.notification.getUserId(),
+                entry.notification.getPackageName())).thenReturn("something else");
+
+        // WHEN the notification is added
+        mEntryListener.onBeforeNotificationAdded(entry);
+
+        // THEN the entry doesn't have any app ops associated with it
+        assertEquals(0, entry.mActiveAppOps.size());
+    }
+
+    private NotificationEntry buildEntry() {
+        mNextNotifId++;
+
+        Notification.Builder n = new Notification.Builder(mContext, "")
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle("Title")
+                .setContentText("Text");
+
+        StatusBarNotification notification =
+                new StatusBarNotification(
+                        TEST_PACKAGE_NAME,
+                        TEST_PACKAGE_NAME,
+                        mNextNotifId,
+                        null,
+                        TEST_UID,
+                        0,
+                        n.build(),
+                        new UserHandle(ActivityManager.getCurrentUser()),
+                        null,
+                        0);
+        return new NotificationEntry(notification);
+    }
+
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index fdbf090..c1f8885 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -182,6 +182,7 @@
             subs.add(subscription);
         }
         when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs);
+        when(mMockSm.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subs);
         mNetworkController.doUpdateMobileControllers();
     }
 
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index 295b3d8..be9ba43 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -26,6 +26,6 @@
 LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
-LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor libpac
+LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor
 
 include $(BUILD_PACKAGE)
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index bb5d288..a07411d 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6801,7 +6801,6 @@
     // ACTION: Tap & Pay -> Default Application Setting -> Use Default
     // OS: Q
     ACTION_NFC_PAYMENT_ALWAYS_SETTING = 1623;
-    // ---- End Q Constants, all Q constants go above this line ----
 
     // OPEN: Settings > System > Input & Gesture > Skip song gesture
     // OS: Q
@@ -6811,6 +6810,10 @@
     // OS: Q
     SETTINGS_GESTURE_SILENCE = 1625;
 
+    // OPEN: Settings > System > Input & Gesture > Tap screen gesture
+    // OS: Q
+    SETTINGS_GESTURE_TAP_SCREEN = 1626;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index cf9f233..8ffadde 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -462,7 +462,7 @@
             return false;
         }
 
-        endGestureDetection();
+        endGestureDetection(true);
 
         mAms.onGesture(gestureId);
 
@@ -472,7 +472,7 @@
     @Override
     public boolean onGestureCancelled(MotionEvent event, int policyFlags) {
         if (mCurrentState == STATE_GESTURE_DETECTING) {
-            endGestureDetection();
+            endGestureDetection(event.getActionMasked() == MotionEvent.ACTION_UP);
             return true;
         } else if (mCurrentState == STATE_TOUCH_EXPLORING) {
             // If the finger is still moving, pass the event on.
@@ -804,13 +804,19 @@
         }
     }
 
-    private void endGestureDetection() {
+    private void endGestureDetection(boolean interactionEnd) {
         mAms.onTouchInteractionEnd();
 
         // Announce the end of the gesture recognition.
         sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
-        // Announce the end of a the touch interaction.
-        sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+        if (interactionEnd) {
+            // Announce the end of a the touch interaction.
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+        } else {
+            // If gesture detection is end, but user doesn't release the finger, announce the
+            // transition to exploration state.
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
+        }
 
         mExitGestureDetectionModeDelayed.cancel();
         mCurrentState = STATE_TOUCH_EXPLORING;
@@ -889,7 +895,6 @@
         MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
         if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
             final int pointerIdBits = event.getPointerIdBits();
-            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
             sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags);
         }
     }
@@ -1148,8 +1153,8 @@
             sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
             // Clearing puts is in touch exploration state with a finger already
             // down, so announce the transition to exploration state.
-            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
             clear();
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 24fd7b9..c992da4 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -252,9 +252,8 @@
     @Override // from AbstractMasterSystemService
     protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
             boolean disabled) {
-        return new AutofillManagerServiceImpl(this, mLock, mRequestsHistory,
-                mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, mAutofillCompatState,
-                disabled);
+        return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory,
+                mWtfHistory, resolvedUserId, mUi, mAutofillCompatState, disabled);
     }
 
     @Override // AbstractMasterSystemService
@@ -291,6 +290,13 @@
         return mSupportedSmartSuggestionModes;
     }
 
+    /**
+     * Logs a request so it's dumped later...
+     */
+    void logRequestLocked(@NonNull String historyItem) {
+        mRequestsHistory.log(historyItem);
+    }
+
     // Called by AutofillManagerServiceImpl, doesn't need to check permission
     boolean isInstantServiceAllowed() {
         return mAllowInstantService;
@@ -701,6 +707,11 @@
         public void onBackKeyPressed() {
             if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
             mUi.hideAll(null);
+            synchronized (mLock) {
+                final AutofillManagerServiceImpl service =
+                        getServiceForUserLocked(UserHandle.getCallingUserId());
+                service.onBackKeyPressed();
+            }
         }
 
         @Override
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index a6bb049..954b67e 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -108,7 +108,6 @@
 
     private static final Random sRandom = new Random();
 
-    private final LocalLog mRequestsHistory;
     private final LocalLog mUiLatencyHistory;
     private final LocalLog mWtfHistory;
     private final FieldClassificationStrategy mFieldClassificationStrategy;
@@ -166,12 +165,12 @@
     @Nullable
     private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService;
 
-    AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
+    AutofillManagerServiceImpl(AutofillManagerService master, Object lock,
             LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
-            AutofillCompatState autofillCompatState, boolean disabled) {
+            AutofillCompatState autofillCompatState,
+            boolean disabled) {
         super(master, lock, userId);
 
-        mRequestsHistory = requestsHistory;
         mUiLatencyHistory = uiLatencyHistory;
         mWtfHistory = wtfHistory;
         mUi = ui;
@@ -187,6 +186,15 @@
     }
 
     @GuardedBy("mLock")
+    void onBackKeyPressed() {
+        final RemoteAugmentedAutofillService remoteService =
+                getRemoteAugmentedAutofillServiceLocked();
+        if (remoteService != null) {
+            remoteService.onDestroyAutofillWindowsRequest();
+        }
+    }
+
+    @GuardedBy("mLock")
     @Override // from PerUserSystemService
     protected boolean updateLocked(boolean disabled) {
         destroySessionsLocked();
@@ -301,7 +309,7 @@
                 + " s=" + mInfo.getServiceInfo().packageName
                 + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds
                 + " hc=" + hasCallback + " f=" + flags;
-        mRequestsHistory.log(historyItem);
+        mMaster.logRequestLocked(historyItem);
 
         newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags);
 
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index a8ff9b0..5d8d8fa 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -109,8 +109,8 @@
     /**
      * Called by {@link Session} when it's time to destroy all augmented autofill requests.
      */
-    public void onDestroyAutofillWindowsRequest(int sessionId) {
-        scheduleAsyncRequest((s) -> s.onDestroyFillWindowRequest(sessionId));
+    public void onDestroyAutofillWindowsRequest() {
+        scheduleAsyncRequest((s) -> s.onDestroyAllFillWindowsRequest());
     }
 
     // TODO(b/111330312): inline into PendingAutofillRequest if it doesn't have any other subclass
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index cf4963c..7dfd8fe 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2610,6 +2610,13 @@
                     + " when server returned null for session " + this.id);
         }
 
+        final String historyItem =
+                "aug:id=" + id + " u=" + uid + " m=" + mode
+                + " a=" + ComponentName.flattenToShortString(mComponentName)
+                + " f=" + mCurrentViewId
+                + " s=" + remoteService.getComponentName();
+        mService.getMaster().logRequestLocked(historyItem);
+
         final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
 
         // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
@@ -2619,7 +2626,7 @@
                 currentValue);
 
         if (mAugmentedAutofillDestroyer == null) {
-            mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest(id);
+            mAugmentedAutofillDestroyer = () -> remoteService.onDestroyAutofillWindowsRequest();
         }
         return mAugmentedAutofillDestroyer;
     }
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 529430c..a7bada0 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -562,7 +562,7 @@
     private void registerTransportsFromPackage(
             String packageName, Predicate<ComponentName> transportComponentFilter) {
         try {
-            mPackageManager.getPackageInfo(packageName, 0);
+            mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
         } catch (PackageManager.NameNotFoundException e) {
             Slog.e(TAG, "Trying to register transports from package not found " + packageName);
             return;
@@ -599,7 +599,8 @@
             return false;
         }
         try {
-            PackageInfo packInfo = mPackageManager.getPackageInfo(transport.getPackageName(), 0);
+            PackageInfo packInfo =
+                    mPackageManager.getPackageInfoAsUser(transport.getPackageName(), 0, mUserId);
             if ((packInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
                     == 0) {
                 Slog.w(TAG, "Transport package " + transport.getPackageName() + " not privileged");
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 3a8966a..79f8a7e 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -494,20 +494,18 @@
                 mUserId);
 
         mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null");
-        mBaseStateDir.mkdirs();
-        if (!SELinux.restorecon(mBaseStateDir)) {
-            Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
-        }
-
-        mDataDir = checkNotNull(dataDir, "dataDir cannot be null");
-        // TODO(b/120424138): Remove when the system user moves out of the cache dir. The cache dir
-        // is managed by init.rc so we don't have to create it below.
-        if (userId != UserHandle.USER_SYSTEM) {
-            mDataDir.mkdirs();
-            if (!SELinux.restorecon(mDataDir)) {
-                Slog.w(TAG, "SELinux restorecon failed on " + mDataDir);
+        // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE
+        // directory. Per-user CE directories are managed by vold.
+        if (userId == UserHandle.USER_SYSTEM) {
+            mBaseStateDir.mkdirs();
+            if (!SELinux.restorecon(mBaseStateDir)) {
+                Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
             }
         }
+
+        // TODO (b/120424138): The system user currently uses the cache which is managed by init.rc
+        // Initialization and restorecon is managed by vold for per-user CE directories.
+        mDataDir = checkNotNull(dataDir, "dataDir cannot be null");
         mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
 
         // Receivers for scheduled backups and transport initialization operations.
@@ -584,7 +582,7 @@
         mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
 
         // Power management
-        mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
+        mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*-" + userId);
     }
 
     void initializeBackupEnableState() {
@@ -1352,7 +1350,7 @@
     private List<PackageInfo> allAgentPackages() {
         // !!! TODO: cache this and regenerate only when necessary
         int flags = PackageManager.GET_SIGNING_CERTIFICATES;
-        List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
+        List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(flags, mUserId);
         int numPackages = packages.size();
         for (int a = numPackages - 1; a >= 0; a--) {
             PackageInfo pkg = packages.get(a);
@@ -1366,8 +1364,8 @@
                     // we will need the shared library path, so look that up and store it here.
                     // This is used implicitly when we pass the PackageInfo object off to
                     // the Activity Manager to launch the app for backup/restore purposes.
-                    app = mPackageManager.getApplicationInfo(pkg.packageName,
-                            PackageManager.GET_SHARED_LIBRARY_FILES);
+                    app = mPackageManager.getApplicationInfoAsUser(pkg.packageName,
+                            PackageManager.GET_SHARED_LIBRARY_FILES, mUserId);
                     pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles;
                     pkg.applicationInfo.sharedLibraryInfos = app.sharedLibraryInfos;
                 }
@@ -1392,7 +1390,7 @@
             notification.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES
                     | Intent.FLAG_RECEIVER_FOREGROUND);
             notification.putExtra(BACKUP_FINISHED_PACKAGE_EXTRA, packageName);
-            mContext.sendBroadcastAsUser(notification, UserHandle.OWNER);
+            mContext.sendBroadcastAsUser(notification, UserHandle.of(mUserId));
         }
 
         mProcessedPackagesJournal.addPackage(packageName);
@@ -2208,11 +2206,10 @@
     /** Used by both incremental and full restore to restore widget data. */
     public void restoreWidgetData(String packageName, byte[] widgetData) {
         // Apply the restored widget state and generate the ID update for the app
-        // TODO: http://b/22388012
         if (MORE_DEBUG) {
             Slog.i(TAG, "Incorporating restored widget data");
         }
-        AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, UserHandle.USER_SYSTEM);
+        AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, mUserId);
     }
 
     // *****************************
@@ -2291,20 +2288,6 @@
 
     /** Sent from an app's backup agent to let the service know that there's new data to backup. */
     public void dataChanged(final String packageName) {
-        final int callingUserHandle = UserHandle.getCallingUserId();
-        if (callingUserHandle != UserHandle.USER_SYSTEM) {
-            // TODO: http://b/22388012
-            // App is running under a non-owner user profile.  For now, we do not back
-            // up data from secondary user profiles.
-            // TODO: backups for all user profiles although don't add backup for profiles
-            // without adding admin control in DevicePolicyManager.
-            if (MORE_DEBUG) {
-                Slog.v(TAG, "dataChanged(" + packageName + ") ignored because it's user "
-                        + callingUserHandle);
-            }
-            return;
-        }
-
         final HashSet<String> targets = dataChangedTargets(packageName);
         if (targets == null) {
             Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
@@ -2921,7 +2904,7 @@
         try {
             int transportUid =
                     mContext.getPackageManager()
-                            .getPackageUid(transportComponent.getPackageName(), 0);
+                            .getPackageUidAsUser(transportComponent.getPackageName(), 0, mUserId);
             if (callingUid != transportUid) {
                 throw new SecurityException("Only the transport can change its description");
             }
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 862ca71..cfc129e 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -45,6 +45,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SELinux;
+import android.os.UserHandle;
 import android.os.WorkSource;
 
 import com.android.internal.annotations.GuardedBy;
@@ -686,8 +687,12 @@
                     ParcelFileDescriptor.open(
                             mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE);
 
-            if (!SELinux.restorecon(mBackupDataFile)) {
-                mReporter.onRestoreconFailed(mBackupDataFile);
+            // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE
+            // directory. Per-user CE directories are managed by vold.
+            if (mUserId == UserHandle.USER_SYSTEM) {
+                if (!SELinux.restorecon(mBackupDataFile)) {
+                    mReporter.onRestoreconFailed(mBackupDataFile);
+                }
             }
 
             IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()");
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index c7f3315..b3d9fbc 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -68,6 +68,8 @@
 public class FullRestoreEngine extends RestoreEngine {
 
     private final UserBackupManagerService mBackupManagerService;
+    private final int mUserId;
+
     // Task in charge of monitoring timeouts
     private final BackupRestoreTask mMonitorTask;
 
@@ -146,6 +148,7 @@
                 backupManagerService.getAgentTimeoutParameters(),
                 "Timeout parameters cannot be null");
         mIsAdbRestore = isAdbRestore;
+        mUserId = backupManagerService.getUserId();
     }
 
     public IBackupAgent getAgent() {
@@ -272,7 +275,7 @@
                                         instream, mBackupManagerService.getContext(),
                                         mDeleteObserver, mManifestSignatures,
                                         mPackagePolicies, info, installerPackageName,
-                                        bytesReadListener, mBackupManagerService.getUserId());
+                                        bytesReadListener, mUserId);
                                 // good to go; promote to ACCEPT
                                 mPackagePolicies.put(pkg, isSuccessfullyInstalled
                                         ? RestorePolicy.ACCEPT
@@ -329,9 +332,8 @@
                         }
 
                         try {
-                            mTargetApp =
-                                    mBackupManagerService.getPackageManager().getApplicationInfo(
-                                            pkg, 0);
+                            mTargetApp = mBackupManagerService.getPackageManager()
+                                    .getApplicationInfoAsUser(pkg, 0, mUserId);
 
                             // If we haven't sent any data to this app yet, we probably
                             // need to clear it first. Check that.
@@ -684,7 +686,7 @@
         String packageListString = Settings.Secure.getStringForUser(
                 mBackupManagerService.getContext().getContentResolver(),
                 Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
-                mBackupManagerService.getUserId());
+                mUserId);
         if (TextUtils.isEmpty(packageListString)) {
             return false;
         }
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 5284d94..d01f77b 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -360,7 +360,6 @@
 
         // If we're starting a full-system restore, set up to begin widget ID remapping
         if (mIsSystemRestore) {
-            // TODO: http://b/22388012
             AppWidgetBackupBridge.restoreStarting(mUserId);
         }
 
@@ -1079,7 +1078,6 @@
         }
 
         // Kick off any work that may be needed regarding app widget restores
-        // TODO: http://b/22388012
         AppWidgetBackupBridge.restoreFinished(mUserId);
 
         // If this was a full-system restore, record the ancestral
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index dc0f602..e4bbcd6 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -32,6 +32,7 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.LocalLog;
 import android.util.Slog;
 import android.view.contentcapture.IContentCaptureManager;
 
@@ -69,6 +70,8 @@
 
     private final LocalService mLocalService = new LocalService();
 
+    private final LocalLog mRequestsHistory = new LocalLog(20);
+
     public ContentCaptureManagerService(@NonNull Context context) {
         super(context, new FrameworkResourcesServiceNameResolver(context,
                 com.android.internal.R.string.config_defaultContentCaptureService),
@@ -154,6 +157,13 @@
         }
     }
 
+    /**
+     * Logs a request so it's dumped later...
+     */
+    void logRequestLocked(@NonNull String historyItem) {
+        mRequestsHistory.log(historyItem);
+    }
+
     private ActivityManagerInternal getAmInternal() {
         synchronized (mLock) {
             if (mAm == null) {
@@ -217,9 +227,29 @@
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
 
+            boolean showHistory = true;
+            if (args != null) {
+                for (String arg : args) {
+                    switch(arg) {
+                        case "--no-history":
+                            showHistory = false;
+                            break;
+                        case "--help":
+                            pw.println("Usage: dumpsys content_capture [--no-history]");
+                            return;
+                        default:
+                            Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
+                    }
+                }
+            }
+
             synchronized (mLock) {
                 dumpLocked("", pw);
             }
+            if (showHistory) {
+                pw.println(); pw.println("Requests history:"); pw.println();
+                mRequestsHistory.reverseDump(fd, pw, args);
+            }
         }
 
         @Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 09aa421..8d2c79b 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -17,6 +17,9 @@
 package com.android.server.contentcapture;
 
 import static android.service.contentcapture.ContentCaptureService.setClientState;
+import static android.view.contentcapture.ContentCaptureSession.STATE_DISABLED;
+import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
+import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
 
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -36,10 +39,11 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.service.contentcapture.ContentCaptureService;
+import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
-import android.view.contentcapture.ContentCaptureSession;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
@@ -48,6 +52,7 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Per-user instance of {@link ContentCaptureManagerService}.
@@ -72,12 +77,14 @@
     @GuardedBy("mLock")
     private RemoteContentCaptureService mRemoteService;
 
+    private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
+            new ContentCaptureServiceRemoteCallback();
+
     // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
 
     ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
             @NonNull Object lock, boolean disabled, @UserIdInt int userId) {
         super(master, lock, userId);
-
         updateRemoteServiceLocked(disabled);
     }
 
@@ -100,10 +107,10 @@
         }
 
         if (!disabled) {
-            mRemoteService = new RemoteContentCaptureService(
-                  mMaster.getContext(),
-                  ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, mUserId, this,
-                  mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+            mRemoteService = new RemoteContentCaptureService(mMaster.getContext(),
+                    ContentCaptureService.SERVICE_INTERFACE, serviceComponentName,
+                    mRemoteServiceCallback, mUserId, this, mMaster.isBindInstantServiceAllowed(),
+                    mMaster.verbose);
         }
     }
 
@@ -162,14 +169,24 @@
             @NonNull ComponentName componentName, int taskId, int displayId,
             @NonNull String sessionId, int uid, int flags,
             @NonNull IResultReceiver clientReceiver) {
-        if (!isEnabledLocked()) {
+
+        final ComponentName serviceComponentName = getServiceComponentName();
+        final boolean enabled = isEnabledLocked();
+        final String historyItem =
+                "id=" + sessionId + " uid=" + uid
+                + " a=" + ComponentName.flattenToShortString(componentName)
+                + " t=" + taskId + " d=" + displayId
+                + " s=" + ComponentName.flattenToShortString(serviceComponentName)
+                + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
+        mMaster.logRequestLocked(historyItem);
+
+        if (!enabled) {
             // TODO: it would be better to split in differet reasons, like
             // STATE_DISABLED_NO_SERVICE and STATE_DISABLED_BY_DEVICE_POLICY
-            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_NO_SERVICE,
+            setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                     /* binder= */ null);
             return;
         }
-        final ComponentName serviceComponentName = getServiceComponentName();
         if (serviceComponentName == null) {
             // TODO(b/111276913): this happens when the system service is starting, we should
             // probably handle it in a more elegant way (like waiting for boot_complete or
@@ -184,7 +201,7 @@
         if (existingSession != null) {
             Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
                     + ": ignoring because it already exists for " + existingSession.mActivityToken);
-            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_DUPLICATED_ID,
+            setClientState(clientReceiver, STATE_DISABLED | STATE_DUPLICATED_ID,
                     /* binder=*/ null);
             return;
         }
@@ -197,8 +214,7 @@
             // TODO(b/119613670): log metrics
             Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
                     + ": ignoring because service is not set");
-            // TODO(b/111276913): use a new disabled state?
-            setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_NO_SERVICE,
+            setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE,
                     /* binder= */ null);
             return;
         }
@@ -338,4 +354,50 @@
         }
         return null;
     }
+
+    private final class ContentCaptureServiceRemoteCallback extends
+            IContentCaptureServiceCallback.Stub {
+
+        @Override
+        public void setContentCaptureWhitelist(List<String> packages,
+                List<ComponentName> activities) {
+            if (mMaster.verbose) {
+                Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+                        + activities + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void setActivityContentCaptureEnabled(ComponentName activity, boolean enabled) {
+            if (mMaster.verbose) {
+                Log.v(TAG, "setActivityContentCaptureEnabled(activity=" + activity + ", enabled="
+                        + enabled + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void setPackageContentCaptureEnabled(String packageName, boolean enabled) {
+            if (mMaster.verbose) {
+                Log.v(TAG,
+                        "setPackageContentCaptureEnabled(packageName=" + packageName + ", enabled="
+                                + enabled + ")");
+            }
+            // TODO(b/122595322): implement
+            // TODO(b/119613670): log metrics
+        }
+
+        @Override
+        public void getContentCaptureDisabledActivities(IResultReceiver receiver) {
+            // TODO(b/122595322): implement
+        }
+
+        @Override
+        public void getContentCaptureDisabledPackages(IResultReceiver receiver) {
+            // TODO(b/122595322): implement
+        }
+    }
 }
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index ebe0083..3c52e17 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -83,6 +83,8 @@
      */
     @GuardedBy("mLock")
     public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
+        mService.getMaster().logRequestLocked("snapshot: id=" + mId);
+
         mRemoteService.onActivitySnapshotRequest(mId, snapshotData);
     }
 
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index 82416286..12742ca 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.service.contentcapture.IContentCaptureService;
+import android.service.contentcapture.IContentCaptureServiceCallback;
 import android.service.contentcapture.SnapshotData;
 import android.text.format.DateUtils;
 import android.util.Slog;
@@ -35,12 +36,15 @@
 
     private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
 
+    private final IBinder mServerCallback;
+
     RemoteContentCaptureService(Context context, String serviceInterface,
-            ComponentName componentName, int userId,
+            ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
             ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
             boolean verbose) {
-        super(context, serviceInterface, componentName, userId, callbacks,
+        super(context, serviceInterface, serviceComponentName, userId, callbacks,
                 bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
+        mServerCallback = callback.asBinder();
 
         // Bind right away, which will trigger a onConnected() on service's
         scheduleBind();
@@ -69,7 +73,11 @@
             scheduleUnbind();
         }
         try {
-            mService.onConnectedStateChanged(state);
+            if (state) {
+                mService.onConnected(mServerCallback);
+            } else {
+                mService.onDisconnected();
+            }
         } catch (Exception e) {
             Slog.w(mTag, "Exception calling onConnectedStateChanged(" + state + "): " + e);
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d0666b9..d6f3e2b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4879,7 +4879,7 @@
         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                 new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
-                mContext, mTrackerHandler, new NetworkMisc(networkMisc), this);
+                mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS);
         // Make sure the network capabilities reflect what the agent info says.
         nai.networkCapabilities = mixInCapabilities(nai, nc);
         final String extraInfo = networkInfo.getExtraInfo();
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 869d564..0b4c01e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -257,6 +257,9 @@
         packageManagerInternal.setLocationPackagesProvider(
                 userId -> mContext.getResources().getStringArray(
                         com.android.internal.R.array.config_locationProviderPackageNames));
+        packageManagerInternal.setLocationExtraPackagesProvider(
+                userId -> mContext.getResources().getStringArray(
+                      com.android.internal.R.array.config_locationExtraPackageNames));
 
         // most startup is deferred until systemRunning()
     }
@@ -1041,12 +1044,13 @@
 
         @Override
         public void onSetProperties(ProviderProperties properties) {
-            // move calls coming from below LMS onto a different thread to avoid deadlock
-            runInternal(() -> {
-                synchronized (mLock) {
-                    mProperties = properties;
-                }
-            });
+            // because this does not invoke any other methods which might result in calling back
+            // into the location provider, it is safe to run this on the calling thread. it is also
+            // currently necessary to run this on the calling thread to ensure that property changes
+            // are publicly visibly immediately, ie for mock providers which are created.
+            synchronized (mLock) {
+                mProperties = properties;
+            }
         }
 
         @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index b0ca2df..aed0684 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -17,13 +17,11 @@
 package com.android.server;
 
 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
-import static android.Manifest.permission.DUMP;
 import static android.Manifest.permission.NETWORK_SETTINGS;
 import static android.Manifest.permission.NETWORK_STACK;
 import static android.Manifest.permission.SHUTDOWN;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
-import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
@@ -40,6 +38,7 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
+
 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
@@ -53,11 +52,9 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.INetd;
-import android.net.TetherStatsParcel;
 import android.net.INetworkManagementEventObserver;
 import android.net.ITetheringStatsProvider;
 import android.net.InterfaceConfiguration;
@@ -69,18 +66,15 @@
 import android.net.NetworkStats;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.TetherStatsParcel;
 import android.net.UidRange;
-import android.net.UidRangeParcel;
 import android.net.util.NetdService;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
-import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
@@ -91,12 +85,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.provider.Settings;
 import android.telephony.DataConnectionRealTimeInfo;
-import android.telephony.PhoneStateListener;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -110,13 +99,11 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
-import com.android.server.NativeDaemonConnector.Command;
-import com.android.server.NativeDaemonConnector.SensitiveArg;
+
 import com.google.android.collect.Maps;
 
 import java.io.BufferedReader;
 import java.io.DataInputStream;
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -124,15 +111,11 @@
 import java.io.PrintWriter;
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.StringTokenizer;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -2153,28 +2136,6 @@
     }
 
     @Override
-    public void startClatd(String interfaceName) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.clatdStart(interfaceName);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public void stopClatd(String interfaceName) throws IllegalStateException {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        try {
-            mNetdService.clatdStop(interfaceName);
-        } catch (RemoteException | ServiceSpecificException e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
     public void registerNetworkActivityListener(INetworkActivityListener listener) {
         mNetworkActivityListeners.register(listener);
     }
diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING
index 93e1dd3..16b12f1 100644
--- a/services/core/java/com/android/server/TEST_MAPPING
+++ b/services/core/java/com/android/server/TEST_MAPPING
@@ -7,7 +7,7 @@
                   "include-annotation": "android.platform.test.annotations.Presubmit"
                 },
                 {
-                  "exclude-annotation": "android.support.test.filters.FlakyTest"
+                  "exclude-annotation": "androidx.test.filters.FlakyTest"
                 }
             ]
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 1c04a94..dd2b33a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -70,6 +70,12 @@
     static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
     static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
     static final String KEY_USE_COMPACTION = "use_compaction";
+    static final String KEY_COMPACT_ACTION_1 = "compact_action_1";
+    static final String KEY_COMPACT_ACTION_2 = "compact_action_2";
+    static final String KEY_COMPACT_THROTTLE_1 = "compact_throttle_1";
+    static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
+    static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
+    static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
 
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
     private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -101,6 +107,12 @@
     private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
     private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
     private static final boolean DEFAULT_USE_COMPACTION = false;
+    public static final int DEFAULT_COMPACT_ACTION_1 = 1;
+    public static final int DEFAULT_COMPACT_ACTION_2 = 3;
+    public static final long DEFAULT_COMPACT_THROTTLE_1 = 5000;
+    public static final long DEFAULT_COMPACT_THROTTLE_2 = 10000;
+    public static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
+    public static final long DEFAULT_COMPACT_THROTTLE_4 = 10000;
 
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -223,6 +235,20 @@
     // Use compaction for background apps.
     public boolean USE_COMPACTION = DEFAULT_USE_COMPACTION;
 
+    // Action for compactAppSome.
+    public int COMPACT_ACTION_1 = DEFAULT_COMPACT_ACTION_1;
+    // Action for compactAppFull;
+    public int COMPACT_ACTION_2 = DEFAULT_COMPACT_ACTION_2;
+
+    // How long we'll skip second compactAppSome after first compactAppSome
+    public long COMPACT_THROTTLE_1 = DEFAULT_COMPACT_THROTTLE_1;
+    // How long we'll skip compactAppSome after compactAppFull
+    public long COMPACT_THROTTLE_2 = DEFAULT_COMPACT_THROTTLE_2;
+    // How long we'll skip compactAppFull after compactAppSome
+    public long COMPACT_THROTTLE_3 = DEFAULT_COMPACT_THROTTLE_3;
+    // How long we'll skip second compactAppFull after first compactAppFull
+    public long COMPACT_THROTTLE_4 = DEFAULT_COMPACT_THROTTLE_4;
+
     // Indicates whether the activity starts logging is enabled.
     // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
     volatile boolean mFlagActivityStartsLoggingEnabled;
@@ -381,6 +407,12 @@
             TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
                     DEFAULT_TOP_TO_FGS_GRACE_DURATION);
             USE_COMPACTION = mParser.getBoolean(KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
+            COMPACT_ACTION_1 = mParser.getInt(KEY_COMPACT_ACTION_1, DEFAULT_COMPACT_ACTION_1);
+            COMPACT_ACTION_2 = mParser.getInt(KEY_COMPACT_ACTION_2, DEFAULT_COMPACT_ACTION_2);
+            COMPACT_THROTTLE_1 = mParser.getLong(KEY_COMPACT_THROTTLE_1, DEFAULT_COMPACT_THROTTLE_1);
+            COMPACT_THROTTLE_2 = mParser.getLong(KEY_COMPACT_THROTTLE_2, DEFAULT_COMPACT_THROTTLE_2);
+            COMPACT_THROTTLE_3 = mParser.getLong(KEY_COMPACT_THROTTLE_3, DEFAULT_COMPACT_THROTTLE_3);
+            COMPACT_THROTTLE_4 = mParser.getLong(KEY_COMPACT_THROTTLE_4, DEFAULT_COMPACT_THROTTLE_4);
 
             updateMaxCachedProcesses();
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bd6fa49..089847d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,6 +32,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 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_ALL;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
@@ -318,7 +319,6 @@
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.TriFunction;
 import com.android.server.AlarmManagerInternal;
-import com.android.server.appop.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.DeviceIdleController;
 import com.android.server.DisplayThread;
@@ -337,6 +337,7 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
 import com.android.server.am.MemoryStatUtil.MemoryStat;
+import com.android.server.appop.AppOpsService;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.pm.Installer;
@@ -658,9 +659,47 @@
 
     /**
      * When an app has restrictions on the other apps that can have associations with it,
-     * it appears here with a set of the allowed apps.
+     * it appears here with a set of the allowed apps and also track debuggability of the app.
      */
-    ArrayMap<String, ArraySet<String>> mAllowedAssociations;
+    ArrayMap<String, PackageAssociationInfo> mAllowedAssociations;
+
+    /**
+     * Tracks association information for a particular package along with debuggability.
+     * <p> Associations for a package A are allowed to package B if B is part of the
+     *     allowed associations for A or if A is debuggable.
+     */
+    private final class PackageAssociationInfo {
+        private final String mSourcePackage;
+        private final ArraySet<String> mAllowedPackageAssociations;
+        private boolean mIsDebuggable;
+
+        PackageAssociationInfo(String sourcePackage, ArraySet<String> allowedPackages,
+                boolean isDebuggable) {
+            mSourcePackage = sourcePackage;
+            mAllowedPackageAssociations = allowedPackages;
+            mIsDebuggable = isDebuggable;
+        }
+
+        /**
+         * Returns true if {@code mSourcePackage} is allowed association with
+         * {@code targetPackage}.
+         */
+        boolean isPackageAssociationAllowed(String targetPackage) {
+            return mIsDebuggable || mAllowedPackageAssociations.contains(targetPackage);
+        }
+
+        boolean isDebuggable() {
+            return mIsDebuggable;
+        }
+
+        void setDebuggable(boolean isDebuggable) {
+            mIsDebuggable = isDebuggable;
+        }
+
+        ArraySet<String> getAllowedPackageAssociations() {
+            return mAllowedPackageAssociations;
+        }
+    }
 
     /**
      * All of the processes we currently have running organized by pid.
@@ -2392,12 +2431,10 @@
      * If it does not, give it an empty set.
      */
     void requireAllowedAssociationsLocked(String packageName) {
-        if (mAllowedAssociations == null) {
-            mAllowedAssociations = new ArrayMap<>(
-                    SystemConfig.getInstance().getAllowedAssociations());
-        }
+        ensureAllowedAssociations();
         if (mAllowedAssociations.get(packageName) == null) {
-            mAllowedAssociations.put(packageName, new ArraySet<>());
+            mAllowedAssociations.put(packageName, new PackageAssociationInfo(packageName,
+                    new ArraySet<>(), /* isDebuggable = */ false));
         }
     }
 
@@ -2408,10 +2445,7 @@
      * association is implicitly allowed.
      */
     boolean validateAssociationAllowedLocked(String pkg1, int uid1, String pkg2, int uid2) {
-        if (mAllowedAssociations == null) {
-            mAllowedAssociations = new ArrayMap<>(
-                    SystemConfig.getInstance().getAllowedAssociations());
-        }
+        ensureAllowedAssociations();
         // Interactions with the system uid are always allowed, since that is the core system
         // that everyone needs to be able to interact with. Also allow reflexive associations
         // within the same uid.
@@ -2419,24 +2453,57 @@
                 || UserHandle.getAppId(uid2) == SYSTEM_UID) {
             return true;
         }
-        // We won't allow this association if either pkg1 or pkg2 has a limit on the
-        // associations that are allowed with it, and the other package is not explicitly
-        // specified as one of those associations.
-        ArraySet<String> pkgs = mAllowedAssociations.get(pkg1);
-        if (pkgs != null) {
-            if (!pkgs.contains(pkg2)) {
-                return false;
-            }
+
+        // Check for association on both source and target packages.
+        PackageAssociationInfo pai = mAllowedAssociations.get(pkg1);
+        if (pai != null && !pai.isPackageAssociationAllowed(pkg2)) {
+            return false;
         }
-        pkgs = mAllowedAssociations.get(pkg2);
-        if (pkgs != null) {
-            return pkgs.contains(pkg1);
+        pai = mAllowedAssociations.get(pkg2);
+        if (pai != null && !pai.isPackageAssociationAllowed(pkg1)) {
+            return false;
         }
         // If no explicit associations are provided in the manifest, then assume the app is
         // allowed associations with any package.
         return true;
     }
 
+    /** Sets up allowed associations for system prebuilt packages from system config (if needed). */
+    private void ensureAllowedAssociations() {
+        if (mAllowedAssociations == null) {
+            ArrayMap<String, ArraySet<String>> allowedAssociations =
+                    SystemConfig.getInstance().getAllowedAssociations();
+            mAllowedAssociations = new ArrayMap<>(allowedAssociations.size());
+            PackageManagerInternal pm = getPackageManagerInternalLocked();
+            for (int i = 0; i < allowedAssociations.size(); i++) {
+                final String pkg = allowedAssociations.keyAt(i);
+                final ArraySet<String> asc = allowedAssociations.valueAt(i);
+
+                // Query latest debuggable flag from package-manager.
+                boolean isDebuggable = false;
+                try {
+                    ApplicationInfo ai = AppGlobals.getPackageManager()
+                            .getApplicationInfo(pkg, MATCH_ALL, 0);
+                    if (ai != null) {
+                        isDebuggable = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                    }
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
+                mAllowedAssociations.put(pkg, new PackageAssociationInfo(pkg, asc, isDebuggable));
+            }
+        }
+    }
+
+    /** Updates allowed associations for app info (specifically, based on debuggability).  */
+    private void updateAssociationForApp(ApplicationInfo appInfo) {
+        ensureAllowedAssociations();
+        PackageAssociationInfo pai = mAllowedAssociations.get(appInfo.packageName);
+        if (pai != null) {
+            pai.setDebuggable((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+        }
+    }
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -10628,7 +10695,6 @@
             ProtoUtils.toDuration(proto, ActivityManagerServiceDumpProcessesProto.LAST_IDLE_TIME, mLastIdleTime, now);
             proto.write(ActivityManagerServiceDumpProcessesProto.LOW_RAM_SINCE_LAST_IDLE_MS, getLowRamTimeSinceIdle(now));
         }
-
     }
 
     void writeProcessesToGcToProto(ProtoOutputStream proto, long fieldId, String dumpPackage) {
@@ -10910,14 +10976,14 @@
     void dumpAllowedAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll, String dumpPackage) {
         boolean needSep = false;
-        boolean printedAnything = false;
 
         pw.println("ACTIVITY MANAGER ALLOWED ASSOCIATION STATE (dumpsys activity allowed-associations)");
         boolean printed = false;
         if (mAllowedAssociations != null) {
             for (int i = 0; i < mAllowedAssociations.size(); i++) {
                 final String pkg = mAllowedAssociations.keyAt(i);
-                final ArraySet<String> asc = mAllowedAssociations.valueAt(i);
+                final ArraySet<String> asc =
+                        mAllowedAssociations.valueAt(i).getAllowedPackageAssociations();
                 boolean printedHeader = false;
                 for (int j = 0; j < asc.size(); j++) {
                     if (dumpPackage == null || pkg.equals(dumpPackage)
@@ -10926,7 +10992,6 @@
                             pw.println("  Allowed associations (by restricted package):");
                             printed = true;
                             needSep = true;
-                            printedAnything = true;
                         }
                         if (!printedHeader) {
                             pw.print("  * ");
@@ -10938,6 +11003,9 @@
                         pw.println(asc.valueAt(j));
                     }
                 }
+                if (mAllowedAssociations.valueAt(i).isDebuggable()) {
+                    pw.println("      (debuggable)");
+                }
             }
         }
         if (!printed) {
@@ -14519,6 +14587,7 @@
                                     + " ssp=" + ssp + " data=" + data);
                             return ActivityManager.BROADCAST_SUCCESS;
                         }
+                        updateAssociationForApp(aInfo);
                         mAtmInternal.onPackageReplaced(aInfo);
                         mServices.updateServiceApplicationInfoLocked(aInfo);
                         sendPackageBroadcastLocked(ApplicationThreadConstants.PACKAGE_REPLACED,
@@ -17798,6 +17867,15 @@
         public void clearPendingBackup(int userId) {
             ActivityManagerService.this.clearPendingBackup(userId);
         }
+
+        /**
+         * When power button is very long pressed, call this interface to do some pre-shutdown work
+         * like persisting database etc.
+         */
+        @Override
+        public void prepareForPossibleShutdown() {
+            ActivityManagerService.this.prepareForPossibleShutdown();
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
@@ -18054,6 +18132,18 @@
         }
     }
 
+    /**
+     * When power button is very long pressed, call this interface to do some pre-shutdown work
+     * like persisting database etc.
+     */
+    public void prepareForPossibleShutdown() {
+        synchronized (this) {
+            if (mUsageStatsService != null) {
+                mUsageStatsService.prepareForPossibleShutdown();
+            }
+        }
+    }
+
     @VisibleForTesting
     public static class Injector {
         private NetworkManagementInternal mNmi;
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index aee16c3..fe27c49 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -44,7 +44,11 @@
      */
     final ArrayList<ProcessRecord> mPendingCompactionProcesses = new ArrayList<ProcessRecord>();
 
-    /*
+    static final int COMPACT_PROCESS_SOME = 1;
+    static final int COMPACT_PROCESS_FULL = 2;
+    static final int COMPACT_PROCESS_MSG = 1;
+
+    /**
      * This thread must be moved to the system background cpuset.
      * If that doesn't happen, it's probably going to draw a lot of power.
      * However, this has to happen after the first updateOomAdjLocked, because
@@ -53,13 +57,22 @@
      */
     final ServiceThread mCompactionThread;
 
-    static final int COMPACT_PROCESS_SOME = 1;
-    static final int COMPACT_PROCESS_FULL = 2;
-    static final int COMPACT_PROCESS_MSG = 1;
-    final Handler mCompactionHandler;
+    final private Handler mCompactionHandler;
 
-    final ActivityManagerService mAm;
-    final ActivityManagerConstants mConstants;
+    final private ActivityManagerService mAm;
+    final private ActivityManagerConstants mConstants;
+
+    final private String COMPACT_ACTION_FILE = "file";
+    final private String COMPACT_ACTION_ANON = "anon";
+    final private String COMPACT_ACTION_FULL = "full";
+
+    final private String compactActionSome;
+    final private String compactActionFull;
+
+    final private long throttleSomeSome;
+    final private long throttleSomeFull;
+    final private long throttleFullSome;
+    final private long throttleFullFull;
 
     public AppCompactor(ActivityManagerService am) {
         mAm = am;
@@ -69,6 +82,41 @@
                 THREAD_PRIORITY_FOREGROUND, true);
         mCompactionThread.start();
         mCompactionHandler = new MemCompactionHandler(this);
+
+        switch(mConstants.COMPACT_ACTION_1) {
+            case 1:
+                compactActionSome = COMPACT_ACTION_FILE;
+                break;
+            case 2:
+                compactActionSome = COMPACT_ACTION_ANON;
+                break;
+            case 3:
+                compactActionSome = COMPACT_ACTION_FULL;
+                break;
+            default:
+                compactActionSome = COMPACT_ACTION_FILE;
+                break;
+        }
+
+        switch(mConstants.COMPACT_ACTION_2) {
+            case 1:
+                compactActionFull = COMPACT_ACTION_FILE;
+                break;
+            case 2:
+                compactActionFull = COMPACT_ACTION_ANON;
+                break;
+            case 3:
+                compactActionFull = COMPACT_ACTION_FULL;
+                break;
+            default:
+                compactActionFull = COMPACT_ACTION_FULL;
+                break;
+        }
+
+        throttleSomeSome = mConstants.COMPACT_THROTTLE_1;
+        throttleSomeFull = mConstants.COMPACT_THROTTLE_2;
+        throttleFullSome = mConstants.COMPACT_THROTTLE_3;
+        throttleFullFull = mConstants.COMPACT_THROTTLE_4;
     }
 
     // Must be called while holding AMS lock.
@@ -128,18 +176,16 @@
                 }
 
                 // basic throttling
+                // use the ActivityManagerConstants knobs to determine whether current/prevous
+                // compaction combo should be throtted or not
                 if (pendingAction == COMPACT_PROCESS_SOME) {
-                    // if we're compacting some, then compact if >10s after last full
-                    // or >5s after last some
-                    if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 5000)) ||
-                        (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000))) {
+                    if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < throttleSomeSome)) ||
+                        (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < throttleSomeFull))) {
                         return;
                     }
                 } else {
-                    // if we're compacting full, then compact if >10s after last full
-                    // or >.5s after last some
-                    if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 500)) ||
-                        (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000))) {
+                    if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < throttleFullSome)) ||
+                        (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < throttleFullFull))) {
                         return;
                     }
                 }
@@ -151,9 +197,9 @@
                     long[] rssBefore = Process.getRss(pid);
                     FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
                     if (pendingAction == COMPACT_PROCESS_SOME) {
-                        action = "file";
+                        action = compactActionSome;
                     } else {
-                        action = "all";
+                        action = compactActionFull;
                     }
                     fos.write(action.getBytes());
                     fos.close();
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index d7cb2bd..d3953b5 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -67,9 +67,10 @@
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class);
+        sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_ALL_APPS, int.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_IN_APPS, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_OUT_APPS, String.class);
-        sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACK_LIST, String.class);
+        sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACKLIST, String.class);
         // add other global settings here...
     }
 
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index ecc3d2d..174ecfa 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -116,6 +116,7 @@
     protected HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
     // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
     protected HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>();
+    protected int mHALDeathCount;
 
     protected class PerformanceStats {
         public int accept; // number of accepted biometrics
@@ -596,6 +597,7 @@
     public void serviceDied(long cookie) {
         Slog.e(getTag(), "HAL died");
         mMetricsLogger.count(getMetrics().tagHalDied(), 1);
+        mHALDeathCount++;
         handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
                 0 /*vendorCode */);
     }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 5a9c1ac..a2aacdd 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -675,6 +675,12 @@
     }
 
     @Override
+    public void serviceDied(long cookie) {
+        super.serviceDied(cookie);
+        mDaemon = null;
+    }
+
+    @Override
     protected void updateActiveGroup(int userId, String clientPackage) {
         IBiometricsFace daemon = getFaceDaemon();
 
@@ -864,6 +870,8 @@
             Slog.e(TAG, "dump formatting failure", e);
         }
         pw.println(dump);
+        pw.println("HAL Deaths: " + mHALDeathCount);
+        mHALDeathCount = 0;
     }
 
     private void dumpProto(FileDescriptor fd) {
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 1613dc9..3db6a74 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -777,6 +777,12 @@
     }
 
     @Override
+    public void serviceDied(long cookie) {
+        super.serviceDied(cookie);
+        mDaemon = null;
+    }
+
+    @Override
     protected void updateActiveGroup(int userId, String clientPackage) {
         IBiometricsFingerprint daemon = getFingerprintDaemon();
 
@@ -1074,6 +1080,8 @@
             Slog.e(TAG, "dump formatting failure", e);
         }
         pw.println(dump);
+        pw.println("HAL Deaths: " + mHALDeathCount);
+        mHALDeathCount = 0;
     }
 
     private void dumpProto(FileDescriptor fd) {
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 6596d27..9d9b1cf 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,8 +16,9 @@
 
 package com.android.server.connectivity;
 
-import android.net.InterfaceConfiguration;
 import android.net.ConnectivityManager;
+import android.net.INetd;
+import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
@@ -59,6 +60,7 @@
         NetworkInfo.State.SUSPENDED,
     };
 
+    private final INetd mNetd;
     private final INetworkManagementService mNMService;
 
     // The network we're running on, and its type.
@@ -76,7 +78,8 @@
     private String mIface;
     private State mState = State.IDLE;
 
-    public Nat464Xlat(INetworkManagementService nmService, NetworkAgentInfo nai) {
+    public Nat464Xlat(NetworkAgentInfo nai, INetd netd, INetworkManagementService nmService) {
+        mNetd = netd;
         mNMService = nmService;
         mNetwork = nai;
     }
@@ -140,7 +143,7 @@
             return;
         }
         try {
-            mNMService.startClatd(baseIface);
+            mNetd.clatdStart(baseIface);
         } catch(RemoteException|IllegalStateException e) {
             Slog.e(TAG, "Error starting clatd on " + baseIface, e);
         }
@@ -162,7 +165,7 @@
      */
     private void enterStoppingState() {
         try {
-            mNMService.stopClatd(mBaseIface);
+            mNetd.clatdStop(mBaseIface);
         } catch(RemoteException|IllegalStateException e) {
             Slog.e(TAG, "Error stopping clatd on " + mBaseIface, e);
         }
@@ -204,7 +207,7 @@
             Slog.e(TAG, "startClat: Can't start clat on null interface");
             return;
         }
-        // TODO: should we only do this if mNMService.startClatd() succeeds?
+        // TODO: should we only do this if mNetd.clatdStart() succeeds?
         Slog.i(TAG, "Starting clatd on " + baseIface);
         enterStartingState(baseIface);
     }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 54c89aa..9ea73fb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -17,6 +17,7 @@
 package com.android.server.connectivity;
 
 import android.content.Context;
+import android.net.INetd;
 import android.net.INetworkMonitor;
 import android.net.LinkProperties;
 import android.net.Network;
@@ -239,12 +240,15 @@
     private static final String TAG = ConnectivityService.class.getSimpleName();
     private static final boolean VDBG = false;
     private final ConnectivityService mConnService;
+    private final INetd mNetd;
+    private final INetworkManagementService mNMS;
     private final Context mContext;
     private final Handler mHandler;
 
     public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
             LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
-            NetworkMisc misc, ConnectivityService connService) {
+            NetworkMisc misc, ConnectivityService connService, INetd netd,
+            INetworkManagementService nms) {
         this.messenger = messenger;
         asyncChannel = ac;
         network = net;
@@ -253,6 +257,8 @@
         networkCapabilities = nc;
         currentScore = score;
         mConnService = connService;
+        mNetd = netd;
+        mNMS = nms;
         mContext = context;
         mHandler = handler;
         networkMisc = misc;
@@ -587,18 +593,18 @@
 
     public void updateClat(INetworkManagementService netd) {
         if (Nat464Xlat.requiresClat(this)) {
-            maybeStartClat(netd);
+            maybeStartClat();
         } else {
             maybeStopClat();
         }
     }
 
     /** Ensure clat has started for this network. */
-    public void maybeStartClat(INetworkManagementService netd) {
+    public void maybeStartClat() {
         if (clatd != null && clatd.isStarted()) {
             return;
         }
-        clatd = new Nat464Xlat(netd, this);
+        clatd = new Nat464Xlat(this, mNetd, mNMS);
         clatd.start();
     }
 
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 3ea9810..9789688 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -282,6 +282,7 @@
     private void setCurrentProxyScript(String script) {
         if (mProxyService == null) {
             Log.e(TAG, "setCurrentProxyScript: no proxy service");
+            return;
         }
         try {
             mProxyService.setPacFile(script);
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index bfcc629..aaf9cbc 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -141,10 +141,7 @@
             final long runtime = nowUptime - startUptime;
 
 
-            if (startUptime == 0) {
-                wtf("Job " + jobId + " start uptime not found: "
-                        + " params=" + jobParametersToString(params));
-            } else if (runtime > 60 * 1000) {
+            if (runtime > 60 * 1000) {
                 // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
                 // (1 minute threshold.)
                 // Also don't wtf when it's not ready to sync.
diff --git a/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java b/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java
index 18d328d..137833c 100644
--- a/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/ArcInitiationActionFromAvr.java
@@ -51,6 +51,13 @@
         }
         switch (cmd.getOpcode()) {
             case Constants.MESSAGE_FEATURE_ABORT:
+                if ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_INITIATE_ARC) {
+                    audioSystem().setArcStatus(false);
+                    finish();
+                    return true;
+                } else {
+                    return false;
+                }
             case Constants.MESSAGE_REPORT_ARC_TERMINATED:
                 audioSystem().setArcStatus(false);
                 finish();
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index ff029c1..297a418 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -17,6 +17,7 @@
 package com.android.server.hdmi;
 
 import android.annotation.IntDef;
+import android.annotation.StringDef;
 import android.hardware.hdmi.HdmiDeviceInfo;
 
 import java.lang.annotation.Retention;
@@ -222,6 +223,15 @@
     static final int AUDIO_CODEC_WMAPRO = 0xE; // Support WMA-Pro
     static final int AUDIO_CODEC_MAX = 0xF;
 
+    @StringDef({
+        AUDIO_DEVICE_ARC_IN,
+        AUDIO_DEVICE_SPDIF,
+    })
+    public @interface AudioDevice {}
+
+    static final String AUDIO_DEVICE_ARC_IN = "ARC_IN";
+    static final String AUDIO_DEVICE_SPDIF = "SPDIF";
+
     // Bit mask used to get the routing path of the top level device.
     // When &'d with the path 1.2.2.0 (0x1220), for instance, gives 1.0.0.0.
     static final int ROUTING_PATH_TOP_MASK = 0xF000;
diff --git a/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java b/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java
index 0495ff8..7187319 100644
--- a/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java
+++ b/services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java
@@ -50,8 +50,10 @@
             if (mState != STATE_WAITING_FOR_FEATURE_ABORT) {
                 return false;
             }
-            finishAction(false);
-            return true;
+            if ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE) {
+                finishAction(false);
+                return true;
+            }
         }
         return false;
     }
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
index ba21b78..df0dc77 100755
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.util.Slog;
 
@@ -51,6 +52,10 @@
     private static final int STATE_WAITING_FOR_OSD_NAME = 3;
     // State in which the action is waiting for gathering vendor id of non-local devices.
     private static final int STATE_WAITING_FOR_VENDOR_ID = 4;
+    // State in which the action is waiting for devices to be ready.
+    private static final int STATE_WAITING_FOR_DEVICES = 5;
+    // State in which the action is waiting for gathering power status of non-local devices.
+    private static final int STATE_WAITING_FOR_POWER = 6;
 
     /**
      * Interface used to report result of device discovery.
@@ -72,6 +77,7 @@
         private int mPhysicalAddress = Constants.INVALID_PHYSICAL_ADDRESS;
         private int mPortId = Constants.INVALID_PORT_ID;
         private int mVendorId = Constants.UNKNOWN_VENDOR_ID;
+        private int mPowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         private String mDisplayName = "";
         private int mDeviceType = HdmiDeviceInfo.DEVICE_INACTIVE;
 
@@ -81,7 +87,7 @@
 
         private HdmiDeviceInfo toHdmiDeviceInfo() {
             return new HdmiDeviceInfo(mLogicalAddress, mPhysicalAddress, mPortId, mDeviceType,
-                    mVendorId, mDisplayName);
+                    mVendorId, mDisplayName, mPowerStatus);
         }
     }
 
@@ -89,7 +95,20 @@
     private final DeviceDiscoveryCallback mCallback;
     private int mProcessedDeviceCount = 0;
     private int mTimeoutRetry = 0;
-    private boolean mIsTvDevice = source().mService.isTvDevice();
+    private boolean mIsTvDevice = localDevice().mService.isTvDevice();
+    private final int mDelayPeriod;
+
+    /**
+     * Constructor.
+     *
+     * @param source an instance of {@link HdmiCecLocalDevice}.
+     * @param delay delay action for this period between query Physical Address and polling
+     */
+    DeviceDiscoveryAction(HdmiCecLocalDevice source, DeviceDiscoveryCallback callback, int delay) {
+        super(source);
+        mCallback = Preconditions.checkNotNull(callback);
+        mDelayPeriod = delay;
+    }
 
     /**
      * Constructor.
@@ -97,8 +116,7 @@
      * @param source an instance of {@link HdmiCecLocalDevice}.
      */
     DeviceDiscoveryAction(HdmiCecLocalDevice source, DeviceDiscoveryCallback callback) {
-        super(source);
-        mCallback = Preconditions.checkNotNull(callback);
+        this(source, callback, 0);
     }
 
     @Override
@@ -117,7 +135,11 @@
 
                 Slog.v(TAG, "Device detected: " + ackedAddress);
                 allocateDevices(ackedAddress);
-                startPhysicalAddressStage();
+                if (mDelayPeriod > 0) {
+                    startToDelayAction();
+                } else {
+                    startPhysicalAddressStage();
+                }
             }
         }, Constants.POLL_ITERATION_REVERSE_ORDER
             | Constants.POLL_STRATEGY_REMOTES_DEVICES, HdmiConfig.DEVICE_POLLING_RETRY);
@@ -131,6 +153,13 @@
         }
     }
 
+    private void startToDelayAction() {
+        Slog.v(TAG, "Waiting for connected devices to be ready");
+        mState = STATE_WAITING_FOR_DEVICES;
+
+        checkAndProceedStage();
+    }
+
     private void startPhysicalAddressStage() {
         Slog.v(TAG, "Start [Physical Address Stage]:" + mDevices.size());
         mProcessedDeviceCount = 0;
@@ -159,6 +188,11 @@
         addTimer(mState, HdmiConfig.TIMEOUT_MS);
     }
 
+    private void delayActionWithTimePeriod(int timeDelay) {
+        mActionTimer.clearTimerMessage();
+        addTimer(mState, timeDelay);
+    }
+
     private void startOsdNameStage() {
         Slog.v(TAG, "Start [Osd Name Stage]:" + mDevices.size());
         mProcessedDeviceCount = 0;
@@ -207,6 +241,29 @@
         addTimer(mState, HdmiConfig.TIMEOUT_MS);
     }
 
+    private void startPowerStatusStage() {
+        Slog.v(TAG, "Start [Power Status Stage]:" + mDevices.size());
+        mProcessedDeviceCount = 0;
+        mState = STATE_WAITING_FOR_POWER;
+
+        checkAndProceedStage();
+    }
+
+    private void queryPowerStatus(int address) {
+        if (!verifyValidLogicalAddress(address)) {
+            checkAndProceedStage();
+            return;
+        }
+
+        mActionTimer.clearTimerMessage();
+
+        if (mayProcessMessageIfCached(address, Constants.MESSAGE_REPORT_POWER_STATUS)) {
+            return;
+        }
+        sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(), address));
+        addTimer(mState, HdmiConfig.TIMEOUT_MS);
+    }
+
     private boolean mayProcessMessageIfCached(int address, int opcode) {
         HdmiCecMessage message = getCecMessageCache().getMessage(address, opcode);
         if (message != null) {
@@ -245,6 +302,16 @@
                     return true;
                 }
                 return false;
+            case STATE_WAITING_FOR_POWER:
+                if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) {
+                    handleReportPowerStatus(cmd);
+                    return true;
+                } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT)
+                        && ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REPORT_POWER_STATUS)) {
+                    handleReportPowerStatus(cmd);
+                    return true;
+                }
+                return false;
             case STATE_WAITING_FOR_DEVICE_POLLING:
                 // Fall through.
             default:
@@ -266,6 +333,7 @@
         current.mPhysicalAddress = HdmiUtils.twoBytesToInt(params);
         current.mPortId = getPortId(current.mPhysicalAddress);
         current.mDeviceType = params[2] & 0xFF;
+        current.mDisplayName = HdmiUtils.getDefaultDeviceName(current.mDeviceType);
 
         // TODO(amyjojo): check if non-TV device needs to update cec switch info.
         // This is to manager CEC device separately in case they don't have address.
@@ -329,6 +397,26 @@
         checkAndProceedStage();
     }
 
+    private void handleReportPowerStatus(HdmiCecMessage cmd) {
+        Preconditions.checkState(mProcessedDeviceCount < mDevices.size());
+
+        DeviceInfo current = mDevices.get(mProcessedDeviceCount);
+        if (current.mLogicalAddress != cmd.getSource()) {
+            Slog.w(TAG, "Unmatched address[expected:" + current.mLogicalAddress + ", actual:"
+                    + cmd.getSource());
+            return;
+        }
+
+        if (cmd.getOpcode() != Constants.MESSAGE_FEATURE_ABORT) {
+            byte[] params = cmd.getParams();
+            int powerStatus = params[0] & 0xFF;
+            current.mPowerStatus = powerStatus;
+        }
+
+        increaseProcessedDeviceCount();
+        checkAndProceedStage();
+    }
+
     private void increaseProcessedDeviceCount() {
         mProcessedDeviceCount++;
         mTimeoutRetry = 0;
@@ -372,6 +460,9 @@
                     startVendorIdStage();
                     return;
                 case STATE_WAITING_FOR_VENDOR_ID:
+                    startPowerStatusStage();
+                    return;
+                case STATE_WAITING_FOR_POWER:
                     wrapUpAndFinish();
                     return;
                 default:
@@ -385,6 +476,9 @@
     private void sendQueryCommand() {
         int address = mDevices.get(mProcessedDeviceCount).mLogicalAddress;
         switch (mState) {
+            case STATE_WAITING_FOR_DEVICES:
+                delayActionWithTimePeriod(mDelayPeriod);
+                return;
             case STATE_WAITING_FOR_PHYSICAL_ADDRESS:
                 queryPhysicalAddress(address);
                 return;
@@ -394,6 +488,9 @@
             case STATE_WAITING_FOR_VENDOR_ID:
                 queryVendorId(address);
                 return;
+            case STATE_WAITING_FOR_POWER:
+                queryPowerStatus(address);
+                return;
             default:
                 return;
         }
@@ -405,13 +502,24 @@
             return;
         }
 
+        if (mState == STATE_WAITING_FOR_DEVICES) {
+            startPhysicalAddressStage();
+            return;
+        }
         if (++mTimeoutRetry < HdmiConfig.TIMEOUT_RETRY) {
             sendQueryCommand();
             return;
         }
         mTimeoutRetry = 0;
         Slog.v(TAG, "Timeout[State=" + mState + ", Processed=" + mProcessedDeviceCount);
-        removeDevice(mProcessedDeviceCount);
+        if (mState != STATE_WAITING_FOR_POWER && mState != STATE_WAITING_FOR_OSD_NAME) {
+            // We don't need to remove the device info if the power status is unknown.
+            // Some device does not have preferred OSD name and does not respond to Give OSD name.
+            // Like LG TV. We can give it default device name and not remove it.
+            removeDevice(mProcessedDeviceCount);
+        } else {
+            increaseProcessedDeviceCount();
+        }
         checkAndProceedStage();
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index e777ce8..86be585 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -77,7 +77,7 @@
 
     private static final int NUM_LOGICAL_ADDRESS = 16;
 
-    private static final int MAX_CEC_MESSAGE_HISTORY = 20;
+    private static final int MAX_CEC_MESSAGE_HISTORY = 200;
 
     // Predicate for whether the given logical address is remote device's one or not.
     private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() {
@@ -682,7 +682,7 @@
 
     void dump(final IndentingPrintWriter pw) {
         for (int i = 0; i < mLocalDevices.size(); ++i) {
-            pw.println("HdmiCecLocalDevice #" + i + ":");
+            pw.println("HdmiCecLocalDevice #" + mLocalDevices.keyAt(i) + ":");
             pw.increaseIndent();
             mLocalDevices.valueAt(i).dump(pw);
             pw.decreaseIndent();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 32dc0261..414f6bb 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -56,16 +56,12 @@
     // Within the timer, a received <User Control Pressed> will start "Press and Hold" behavior.
     // When it expires, we can assume <User Control Release> is received.
     private static final int FOLLOWER_SAFETY_TIMEOUT = 550;
-    /**
-     * Return value of {@link #getLocalPortFromPhysicalAddress(int)}
-     */
-    private static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
-    private static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;
 
     protected final HdmiControlService mService;
     protected final int mDeviceType;
     protected int mAddress;
     protected int mPreferredAddress;
+    @GuardedBy("mLock")
     protected HdmiDeviceInfo mDeviceInfo;
     protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
     protected int mLastKeyRepeatCount = 0;
@@ -717,16 +713,18 @@
         return mDeviceType;
     }
 
-    @ServiceThreadOnly
+    @GuardedBy("mLock")
     HdmiDeviceInfo getDeviceInfo() {
-        assertRunOnServiceThread();
-        return mDeviceInfo;
+        synchronized (mLock) {
+            return mDeviceInfo;
+        }
     }
 
-    @ServiceThreadOnly
+    @GuardedBy("mLock")
     void setDeviceInfo(HdmiDeviceInfo info) {
-        assertRunOnServiceThread();
-        mDeviceInfo = info;
+        synchronized (mLock) {
+            mDeviceInfo = info;
+        }
     }
 
     // Returns true if the logical address is same as the argument.
@@ -1058,47 +1056,6 @@
         pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
     }
 
-    /**
-     * Method to parse target physical address to the port number on the current device.
-     *
-     * <p>This check assumes target address is valid.
-     * @param targetPhysicalAddress is the physical address of the target device
-     * @return
-     * If the target device is under the current device, return the port number of current device
-     * that the target device is connected to.
-     *
-     * <p>If the target device has the same physical address as the current device, return
-     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
-     *
-     * <p>If the target device is not under the current device, return
-     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
-     */
-    protected int getLocalPortFromPhysicalAddress(int targetPhysicalAddress) {
-        int myPhysicalAddress = mService.getPhysicalAddress();
-        if (myPhysicalAddress == targetPhysicalAddress) {
-            return TARGET_SAME_PHYSICAL_ADDRESS;
-        }
-        int finalMask = 0xF000;
-        int mask;
-        int port = 0;
-        for (mask = 0x0F00; mask > 0x000F;  mask >>= 4) {
-            if ((myPhysicalAddress & mask) == 0)  {
-                port = mask & targetPhysicalAddress;
-                break;
-            } else {
-                finalMask |= mask;
-            }
-        }
-        if (finalMask != 0xFFFF && (finalMask & targetPhysicalAddress) == myPhysicalAddress) {
-            while (mask != 0x000F) {
-                mask >>= 4;
-                port >>= 4;
-            }
-            return port;
-        }
-        return TARGET_NOT_UNDER_LOCAL_DEVICE;
-    }
-
     /** Calculates the physical address for {@code activePortId}.
      *
      * <p>This method assumes current device physical address is valid.
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 0e4e334..63214ed 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -26,22 +26,38 @@
 import android.hardware.hdmi.HdmiPortInfo;
 import android.hardware.hdmi.IHdmiControlCallback;
 import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.media.tv.TvContract;
 import android.os.SystemProperties;
+import android.provider.Settings.Global;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.Constants.AudioCodec;
 import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
+import com.android.server.hdmi.HdmiUtils.CodecSad;
+import com.android.server.hdmi.HdmiUtils.DeviceConfig;
 
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.stream.Collectors;
+
 
 /**
  * Represent a logical device of type {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} residing in Android
@@ -77,25 +93,28 @@
     // processing.
     private final HashMap<Integer, String> mTvInputs = new HashMap<>();
 
+    // Copy of mDeviceInfos to guarantee thread-safety.
+    @GuardedBy("mLock")
+    private List<HdmiDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList();
+
     // Map-like container of all cec devices.
     // device id is used as key of container.
     private final SparseArray<HdmiDeviceInfo> mDeviceInfos = new SparseArray<>();
 
     protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
-        mSystemAudioControlFeatureEnabled = true;
-        // TODO(amyjojo) make System Audio Control controllable by users
-        /*mSystemAudioControlFeatureEnabled =
-        mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);*/
-        // TODO(amyjojo): make the map ro property.
-        mTvInputs.put(Constants.CEC_SWITCH_HDMI1,
-                "com.droidlogic.tvinput/.services.Hdmi1InputService/HW5");
-        mTvInputs.put(Constants.CEC_SWITCH_HDMI2,
-                "com.droidlogic.tvinput/.services.Hdmi2InputService/HW6");
-        mTvInputs.put(Constants.CEC_SWITCH_HDMI3,
-                "com.droidlogic.tvinput/.services.Hdmi3InputService/HW7");
+        mRoutingControlFeatureEnabled =
+            mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false);
+        mSystemAudioControlFeatureEnabled =
+            mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);
+        // TODO(amyjojo): Maintain a portId to TvinputId map.
+        mTvInputs.put(2, "com.droidlogic.tvinput/.services.Hdmi1InputService/HW5");
+        mTvInputs.put(4, "com.droidlogic.tvinput/.services.Hdmi2InputService/HW6");
+        mTvInputs.put(1, "com.droidlogic.tvinput/.services.Hdmi3InputService/HW7");
     }
 
+    private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml";
+
     /**
      * Called when a device is newly added or a new device is detected or
      * an existing device is updated.
@@ -167,6 +186,7 @@
             removeDeviceInfo(deviceInfo.getId());
         }
         mDeviceInfos.append(deviceInfo.getId(), deviceInfo);
+        updateSafeDeviceInfoList();
         return oldDeviceInfo;
     }
 
@@ -184,6 +204,7 @@
         if (deviceInfo != null) {
             mDeviceInfos.remove(id);
         }
+        updateSafeDeviceInfoList();
         return deviceInfo;
     }
 
@@ -200,6 +221,24 @@
         return mDeviceInfos.get(HdmiDeviceInfo.idForCecDevice(logicalAddress));
     }
 
+    @ServiceThreadOnly
+    private void updateSafeDeviceInfoList() {
+        assertRunOnServiceThread();
+        List<HdmiDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos);
+        synchronized (mLock) {
+            mSafeAllDeviceInfos = copiedDevices;
+        }
+    }
+
+    @GuardedBy("mLock")
+    List<HdmiDeviceInfo> getSafeCecDevicesLocked() {
+        ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>();
+        for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
+            infoList.add(info);
+        }
+        return infoList;
+    }
+
     private void invokeDeviceEventListener(HdmiDeviceInfo info, int status) {
         mService.invokeDeviceEventListeners(info, status);
     }
@@ -229,7 +268,7 @@
         mTvSystemAudioModeSupport = false;
         // Record the last state of System Audio Control before going to standby
         synchronized (mLock) {
-            SystemProperties.set(
+            mService.writeStringSetting(
                     Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL,
                     mSystemAudioActivated ? "true" : "false");
         }
@@ -240,6 +279,10 @@
     @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress, int reason) {
         assertRunOnServiceThread();
+        if (reason == mService.INITIATED_BY_ENABLE_CEC) {
+            mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(),
+                    getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST);
+        }
         mService.sendCecCommand(
                 HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                         mAddress, mService.getPhysicalAddress(), mDeviceType));
@@ -259,7 +302,10 @@
 
     @Override
     protected int findKeyReceiverAddress() {
-        return Constants.ADDR_TV;
+        if (getActiveSource().isValid()) {
+            return getActiveSource().logicalAddress;
+        }
+        return Constants.ADDR_INVALID;
     }
 
     @VisibleForTesting
@@ -267,7 +313,7 @@
             int systemAudioOnPowerOnProp, boolean lastSystemAudioControlStatus) {
         if ((systemAudioOnPowerOnProp == ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON)
                 || ((systemAudioOnPowerOnProp == USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON)
-                && lastSystemAudioControlStatus)) {
+                && lastSystemAudioControlStatus && isSystemAudioControlFeatureEnabled())) {
             addAndStartAction(new SystemAudioInitiationActionFromAvr(this));
         }
     }
@@ -284,7 +330,7 @@
     @ServiceThreadOnly
     protected void setPreferredAddress(int addr) {
         assertRunOnServiceThread();
-        SystemProperties.set(
+        mService.writeStringSetting(
                 Constants.PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM, String.valueOf(addr));
     }
 
@@ -400,8 +446,11 @@
     @ServiceThreadOnly
     protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
-        reportAudioStatus(message);
+        if (isSystemAudioControlFeatureEnabled()) {
+            reportAudioStatus(message.getSource());
+        } else {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+        }
         return true;
     }
 
@@ -420,7 +469,7 @@
     protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
         assertRunOnServiceThread();
         removeAction(ArcInitiationActionFromAvr.class);
-        if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) {
+        if (!mService.readBooleanSetting(Constants.PROPERTY_ARC_SUPPORT, true)) {
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
         } else if (!isDirectConnectToTv()) {
             HdmiLogger.debug("AVR device is not directly connected with TV");
@@ -459,13 +508,35 @@
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
             return true;
         }
-        AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo();
-        if (deviceInfo == null) {
-            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNABLE_TO_DETERMINE);
-            return true;
+
+        List<DeviceConfig> config = null;
+        File file = new File(SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH);
+        if (file.exists()) {
+            try {
+                InputStream in = new FileInputStream(file);
+                config = HdmiUtils.ShortAudioDescriptorXmlParser.parse(in);
+                in.close();
+            } catch (IOException e) {
+                Slog.e(TAG, "Error reading file: " + file, e);
+            } catch (XmlPullParserException e) {
+                Slog.e(TAG, "Unable to parse file: " + file, e);
+            }
         }
+
         @AudioCodec int[] audioFormatCodes = parseAudioFormatCodes(message.getParams());
-        byte[] sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes);
+        byte[] sadBytes;
+        if (config != null && config.size() > 0) {
+            sadBytes = getSupportedShortAudioDescriptorsFromConfig(config, audioFormatCodes);
+        } else {
+            AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo();
+            if (deviceInfo == null) {
+                mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNABLE_TO_DETERMINE);
+                return true;
+            }
+
+            sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes);
+        }
+
         if (sadBytes.length == 0) {
             mService.maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND);
         } else {
@@ -478,14 +549,127 @@
 
     private byte[] getSupportedShortAudioDescriptors(
             AudioDeviceInfo deviceInfo, @AudioCodec int[] audioFormatCodes) {
-        // TODO(b/80297701) implement
-        return new byte[] {};
+        ArrayList<byte[]> sads = new ArrayList<>(audioFormatCodes.length);
+        for (@AudioCodec int audioFormatCode : audioFormatCodes) {
+            byte[] sad = getSupportedShortAudioDescriptor(deviceInfo, audioFormatCode);
+            if (sad != null) {
+                if (sad.length == 3) {
+
+                    sads.add(sad);
+                } else {
+                    HdmiLogger.warning(
+                            "Dropping Short Audio Descriptor with length %d for requested codec %x",
+                            sad.length, audioFormatCode);
+                }
+            }
+        }
+        return getShortAudioDescriptorBytes(sads);
+    }
+
+    private byte[] getSupportedShortAudioDescriptorsFromConfig(
+            List<DeviceConfig> deviceConfig, @AudioCodec int[] audioFormatCodes) {
+        DeviceConfig deviceConfigToUse = null;
+        for (DeviceConfig device : deviceConfig) {
+            // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name
+            if (device.name.equals("VX_AUDIO_DEVICE_IN_HDMI_ARC")) {
+                deviceConfigToUse = device;
+                break;
+            }
+        }
+        if (deviceConfigToUse == null) {
+            // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name
+            Slog.w(TAG, "sadConfig.xml does not have required device info for "
+                        + "VX_AUDIO_DEVICE_IN_HDMI_ARC");
+            return new byte[0];
+        }
+        HashMap<Integer, byte[]> map = new HashMap<>();
+        ArrayList<byte[]> sads = new ArrayList<>(audioFormatCodes.length);
+        for (CodecSad codecSad : deviceConfigToUse.supportedCodecs) {
+            map.put(codecSad.audioCodec, codecSad.sad);
+        }
+        for (int i = 0; i < audioFormatCodes.length; i++) {
+            if (map.containsKey(audioFormatCodes[i])) {
+                byte[] sad = map.get(audioFormatCodes[i]);
+                if (sad != null && sad.length == 3) {
+                    sads.add(sad);
+                }
+            }
+        }
+        return getShortAudioDescriptorBytes(sads);
+    }
+
+    private byte[] getShortAudioDescriptorBytes(ArrayList<byte[]> sads) {
+        // Short Audio Descriptors are always 3 bytes long.
+        byte[] bytes = new byte[sads.size() * 3];
+        int index = 0;
+        for (byte[] sad : sads) {
+            System.arraycopy(sad, 0, bytes, index, 3);
+            index += 3;
+        }
+        return bytes;
+    }
+
+    /**
+     * Returns a 3 byte short audio descriptor as described in CEC 1.4 table 29 or null if the
+     * audioFormatCode is not supported.
+     */
+    @Nullable
+    private byte[] getSupportedShortAudioDescriptor(
+            AudioDeviceInfo deviceInfo, @AudioCodec int audioFormatCode) {
+        switch (audioFormatCode) {
+            case Constants.AUDIO_CODEC_NONE: {
+                return null;
+            }
+            case Constants.AUDIO_CODEC_LPCM: {
+                return getLpcmShortAudioDescriptor(deviceInfo);
+            }
+            // TODO(b/80297701): implement the rest of the codecs
+            case Constants.AUDIO_CODEC_DD:
+            case Constants.AUDIO_CODEC_MPEG1:
+            case Constants.AUDIO_CODEC_MP3:
+            case Constants.AUDIO_CODEC_MPEG2:
+            case Constants.AUDIO_CODEC_AAC:
+            case Constants.AUDIO_CODEC_DTS:
+            case Constants.AUDIO_CODEC_ATRAC:
+            case Constants.AUDIO_CODEC_ONEBITAUDIO:
+            case Constants.AUDIO_CODEC_DDP:
+            case Constants.AUDIO_CODEC_DTSHD:
+            case Constants.AUDIO_CODEC_TRUEHD:
+            case Constants.AUDIO_CODEC_DST:
+            case Constants.AUDIO_CODEC_WMAPRO:
+            default: {
+                return null;
+            }
+        }
+    }
+
+    @Nullable
+    private byte[] getLpcmShortAudioDescriptor(AudioDeviceInfo deviceInfo) {
+        // TODO(b/80297701): implement
+        return null;
     }
 
     @Nullable
     private AudioDeviceInfo getSystemAudioDeviceInfo() {
-        // TODO(b/80297701) implement
-        // Get the audio device used for system audio mode.
+        AudioManager audioManager = mService.getContext().getSystemService(AudioManager.class);
+        if (audioManager == null) {
+            HdmiLogger.error(
+                    "Error getting system audio device because AudioManager not available.");
+            return null;
+        }
+        AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
+        HdmiLogger.debug("Found %d audio input devices", devices.length);
+        for (AudioDeviceInfo device : devices) {
+            HdmiLogger.debug("%s at port %s", device.getProductName(), device.getPort());
+            HdmiLogger.debug("Supported encodings are %s",
+                    Arrays.stream(device.getEncodings()).mapToObj(
+                            AudioFormat::toLogFriendlyEncoding
+                    ).collect(Collectors.joining(", ")));
+            // TODO(b/80297701) use the actual device type that system audio mode is connected to.
+            if (device.getType() == AudioDeviceInfo.TYPE_HDMI_ARC) {
+                return device;
+            }
+        }
         return null;
     }
 
@@ -583,17 +767,20 @@
             .setWiredDeviceConnectionState(AudioSystem.DEVICE_IN_HDMI, enabled ? 1 : 0, "", "");
     }
 
-    private void reportAudioStatus(HdmiCecMessage message) {
+    void reportAudioStatus(int source) {
         assertRunOnServiceThread();
 
         int volume = mService.getAudioManager().getStreamVolume(AudioManager.STREAM_MUSIC);
         boolean mute = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
         int maxVolume = mService.getAudioManager().getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        int minVolume = mService.getAudioManager().getStreamMinVolume(AudioManager.STREAM_MUSIC);
         int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+        HdmiLogger.debug("Reporting volume %i (%i-%i) as CEC volume %i", volume,
+                minVolume, maxVolume, scaledVolume);
 
         mService.sendCecCommand(
                 HdmiCecMessageBuilder.buildReportAudioStatus(
-                        mAddress, message.getSource(), scaledVolume, mute));
+                        mAddress, source, scaledVolume, mute));
     }
 
     /**
@@ -633,7 +820,7 @@
      */
     private void setSystemAudioMode(boolean newSystemAudioMode) {
         int targetPhysicalAddress = getActiveSource().physicalAddress;
-        int port = getLocalPortFromPhysicalAddress(targetPhysicalAddress);
+        int port = mService.pathToPortId(targetPhysicalAddress);
         if (newSystemAudioMode && port >= 0) {
             switchToAudioInput();
         }
@@ -641,16 +828,18 @@
         // PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE is false when device never needs to be muted.
         boolean currentMuteStatus =
                 mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
-        if (SystemProperties.getBoolean(
-                Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true)
-                && currentMuteStatus == newSystemAudioMode) {
-            mService.getAudioManager()
-                    .adjustStreamVolume(
-                            AudioManager.STREAM_MUSIC,
-                            newSystemAudioMode
-                                    ? AudioManager.ADJUST_UNMUTE
-                                    : AudioManager.ADJUST_MUTE,
-                                    0);
+        if (currentMuteStatus == newSystemAudioMode) {
+            if (mService.readBooleanSetting(
+                    Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true)
+                            || newSystemAudioMode) {
+                mService.getAudioManager()
+                        .adjustStreamVolume(
+                                AudioManager.STREAM_MUSIC,
+                                newSystemAudioMode
+                                        ? AudioManager.ADJUST_UNMUTE
+                                        : AudioManager.ADJUST_MUTE,
+                                0);
+            }
         }
         updateAudioManagerForSystemAudio(newSystemAudioMode);
         synchronized (mLock) {
@@ -688,6 +877,13 @@
         HdmiLogger.debug("[A]UpdateSystemAudio mode[on=%b] output=[%X]", on, device);
     }
 
+    void onSystemAduioControlFeatureSupportChanged(boolean enabled) {
+        setSystemAudioControlFeatureEnabled(enabled);
+        if (enabled) {
+            addAndStartAction(new SystemAudioInitiationActionFromAvr(this));
+        }
+    }
+
     @ServiceThreadOnly
     void setSystemAudioControlFeatureEnabled(boolean enabled) {
         assertRunOnServiceThread();
@@ -697,6 +893,14 @@
     }
 
     @ServiceThreadOnly
+    void setRoutingControlFeatureEnables(boolean enabled) {
+        assertRunOnServiceThread();
+        synchronized (mLock) {
+            mRoutingControlFeatureEnabled = enabled;
+        }
+    }
+
+    @ServiceThreadOnly
     void doManualPortSwitching(int portId, IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         // TODO: validate port ID
@@ -817,7 +1021,7 @@
 
     @Override
     protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
-        int port = getLocalPortFromPhysicalAddress(physicalAddress);
+        int port = mService.pathToPortId(physicalAddress);
         if (isSystemAudioActivated() && port < 0) {
             // If system audio mode is on and the new active source is not under the current device,
             // Will switch to ARC input.
@@ -831,6 +1035,10 @@
     }
 
     protected void routeToInputFromPortId(int portId) {
+        if (!isRoutingControlFeatureEnabled()) {
+            HdmiLogger.debug("Routing Control Feature is not enabled.");
+            return;
+        }
         if (mArcIntentUsed) {
             routeToTvInputFromPortId(portId);
         } else {
@@ -885,7 +1093,7 @@
 
     @Override
     protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
-        int port = getLocalPortFromPhysicalAddress(physicalAddress);
+        int port = mService.pathToPortId(physicalAddress);
         // Routing change or information sent from switches under the current device can be ignored.
         if (port > 0) {
             return;
@@ -918,8 +1126,7 @@
             return;
         }
 
-        int routingInformationPath =
-                getActivePathOnSwitchFromActivePortId(getRoutingPort());
+        int routingInformationPath = mService.portIdToPath(getRoutingPort());
         // If current device is already the leaf of the whole HDMI system, will do nothing.
         if (routingInformationPath == mService.getPhysicalAddress()) {
             HdmiLogger.debug("Current device can't assign valid physical address"
@@ -954,6 +1161,10 @@
     @ServiceThreadOnly
     private void launchDeviceDiscovery() {
         assertRunOnServiceThread();
+        if (hasAction(DeviceDiscoveryAction.class)) {
+            Slog.i(TAG, "Device Discovery Action is in progress. Restarting.");
+            removeAction(DeviceDiscoveryAction.class);
+        }
         DeviceDiscoveryAction action = new DeviceDiscoveryAction(this,
                 new DeviceDiscoveryCallback() {
                     @Override
@@ -977,5 +1188,25 @@
             invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
         }
         mDeviceInfos.clear();
+        updateSafeDeviceInfoList();
     }
+
+    @Override
+    protected void dump(IndentingPrintWriter pw) {
+        pw.println("HdmiCecLocalDeviceAudioSystem:");
+        pw.increaseIndent();
+        pw.println("mSystemAudioActivated: " + mSystemAudioActivated);
+        pw.println("isRoutingFeatureEnabled " + isRoutingControlFeatureEnabled());
+        pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled);
+        pw.println("mTvSystemAudioModeSupport: " + mTvSystemAudioModeSupport);
+        pw.println("mArcEstablished: " + mArcEstablished);
+        pw.println("mArcIntentUsed: " + mArcIntentUsed);
+        pw.println("mRoutingPort: " + getRoutingPort());
+        pw.println("mLocalActivePort: " + getLocalActivePort());
+        HdmiUtils.dumpMap(pw, "mTvInputs:", mTvInputs);
+        HdmiUtils.dumpSparseArray(pw, "mDeviceInfos:", mDeviceInfos);
+        pw.decreaseIndent();
+        super.dump(pw);
+    }
+
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 07db971..7a0c279 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -77,6 +77,10 @@
     @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress, int reason) {
         assertRunOnServiceThread();
+        if (reason == mService.INITIATED_BY_ENABLE_CEC) {
+            mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(),
+                    getDeviceInfo().getDeviceType(), Constants.ADDR_BROADCAST);
+        }
         mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                 mAddress, mService.getPhysicalAddress(), mDeviceType));
         mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
@@ -96,7 +100,7 @@
     @ServiceThreadOnly
     protected void setPreferredAddress(int addr) {
         assertRunOnServiceThread();
-        SystemProperties.set(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK,
+        mService.writeStringSetting(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK,
                 String.valueOf(addr));
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index a95f7f1..ae008b4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -66,6 +66,10 @@
     @LocalActivePort
     protected int mLocalActivePort = Constants.CEC_SWITCH_HOME;
 
+    // Whether the Routing Coutrol feature is enabled or not. False by default.
+    @GuardedBy("mLock")
+    protected boolean mRoutingControlFeatureEnabled;
+
     protected HdmiCecLocalDeviceSource(HdmiControlService service, int deviceType) {
         super(service, deviceType);
     }
@@ -123,7 +127,9 @@
         }
         setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
         updateDevicePowerStatus(logicalAddress, HdmiControlManager.POWER_STATUS_ON);
-        switchInputOnReceivingNewActivePath(physicalAddress);
+        if (isRoutingControlFeatureEnabled()) {
+            switchInputOnReceivingNewActivePath(physicalAddress);
+        }
         return true;
     }
 
@@ -153,6 +159,10 @@
     @ServiceThreadOnly
     protected boolean handleRoutingChange(HdmiCecMessage message) {
         assertRunOnServiceThread();
+        if (!isRoutingControlFeatureEnabled()) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            return true;
+        }
         int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2);
         // if the current device is a pure playback device
         if (!mIsSwitchDevice
@@ -168,6 +178,10 @@
     @ServiceThreadOnly
     protected boolean handleRoutingInformation(HdmiCecMessage message) {
         assertRunOnServiceThread();
+        if (!isRoutingControlFeatureEnabled()) {
+            mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+            return true;
+        }
         int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
         // if the current device is a pure playback device
         if (!mIsSwitchDevice
@@ -204,7 +218,7 @@
     // This method should only be called when the device can be the active source.
     protected void setAndBroadcastActiveSource(HdmiCecMessage message, int physicalAddress) {
         mService.setAndBroadcastActiveSource(
-                message, physicalAddress, getDeviceInfo().getDeviceType());
+                physicalAddress, getDeviceInfo().getDeviceType(), message.getSource());
     }
 
     @ServiceThreadOnly
@@ -279,6 +293,12 @@
         }
     }
 
+    boolean isRoutingControlFeatureEnabled() {
+        synchronized (mLock) {
+            return mRoutingControlFeatureEnabled;
+        }
+    }
+
     // Check if the device is trying to switch to the same input that is active right now.
     // This can help avoid redundant port switching.
     protected boolean isSwitchingToTheSameInput(@LocalActivePort int activePort) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
index c005615..f8b3962 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessage.java
@@ -17,6 +17,7 @@
 package com.android.server.hdmi;
 
 import android.annotation.Nullable;
+
 import libcore.util.EmptyArray;
 
 import java.util.Arrays;
@@ -111,12 +112,11 @@
     @Override
     public String toString() {
         StringBuffer s = new StringBuffer();
-        s.append(String.format("<%s> src: %d, dst: %d",
-                opcodeToString(mOpcode), mSource, mDestination));
+        s.append(String.format("<%s> %X%X:%02X",
+                opcodeToString(mOpcode), mSource, mDestination, mOpcode));
         if (mParams.length > 0) {
-            s.append(", params:");
             for (byte data : mParams) {
-                s.append(String.format(" %02X", data));
+                s.append(String.format(":%02X", data));
             }
         }
         return s.toString();
@@ -133,7 +133,7 @@
             case Constants.MESSAGE_TUNER_STEP_DECREMENT:
                 return "Tuner Step Decrement";
             case Constants.MESSAGE_TUNER_DEVICE_STATUS:
-                return "Tuner Device Staus";
+                return "Tuner Device Status";
             case Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS:
                 return "Give Tuner Device Status";
             case Constants.MESSAGE_RECORD_ON:
@@ -207,7 +207,7 @@
             case Constants.MESSAGE_DEVICE_VENDOR_ID:
                 return "Device Vendor Id";
             case Constants.MESSAGE_VENDOR_COMMAND:
-                return "Vendor Commandn";
+                return "Vendor Command";
             case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN:
                 return "Vendor Remote Button Down";
             case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP:
@@ -215,7 +215,7 @@
             case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
                 return "Give Device Vendor Id";
             case Constants.MESSAGE_MENU_REQUEST:
-                return "Menu REquest";
+                return "Menu Request";
             case Constants.MESSAGE_MENU_STATUS:
                 return "Menu Status";
             case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
@@ -247,7 +247,7 @@
             case Constants.MESSAGE_SET_EXTERNAL_TIMER:
                 return "Set External Timer";
             case Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR:
-                return "Repot Short Audio Descriptor";
+                return "Report Short Audio Descriptor";
             case Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR:
                 return "Request Short Audio Descriptor";
             case Constants.MESSAGE_INITIATE_ARC:
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 2d6e762..46219d5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -20,12 +20,14 @@
 import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
 
 import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH;
+import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
 import static com.android.server.hdmi.Constants.DISABLED;
 import static com.android.server.hdmi.Constants.ENABLED;
 import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE;
 import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING;
 import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE;
 import static com.android.server.hdmi.Constants.OPTION_MHL_SERVICE_CONTROL;
+import static com.android.server.power.ShutdownThread.SHUTDOWN_ACTION_PROPERTY;
 
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
@@ -184,9 +186,10 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             assertRunOnServiceThread();
+            boolean isReboot = SystemProperties.get(SHUTDOWN_ACTION_PROPERTY).contains("1");
             switch (intent.getAction()) {
                 case Intent.ACTION_SCREEN_OFF:
-                    if (isPowerOnOrTransient()) {
+                    if (isPowerOnOrTransient() && !isReboot) {
                         onStandby(STANDBY_SCREEN_OFF);
                     }
                     break;
@@ -202,7 +205,7 @@
                     }
                     break;
                 case Intent.ACTION_SHUTDOWN:
-                    if (isPowerOnOrTransient()) {
+                    if (isPowerOnOrTransient() && !isReboot) {
                         onStandby(STANDBY_SHUTDOWN);
                     }
                     break;
@@ -345,6 +348,10 @@
     @Nullable
     private Looper mIoLooper;
 
+    // Thread safe physical address
+    @GuardedBy("mLock")
+    private int mPhysicalAddress = Constants.INVALID_PHYSICAL_ADDRESS;
+
     // Last input port before switching to the MHL port. Should switch back to this port
     // when the mobile device sends the request one touch play with off.
     // Gets invalidated if we go to other port/input.
@@ -564,7 +571,8 @@
                 Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
                 Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
                 Global.MHL_INPUT_SWITCHING_ENABLED,
-                Global.MHL_POWER_CHARGE_ENABLED
+                Global.MHL_POWER_CHARGE_ENABLED,
+                Global.HDMI_CEC_SWITCH_ENABLED
         };
         for (String s : settings) {
             resolver.registerContentObserver(Global.getUriFor(s), false, mSettingsObserver,
@@ -605,6 +613,24 @@
                     if (isTvDeviceEnabled()) {
                         tv().setSystemAudioControlFeatureEnabled(enabled);
                     }
+                    if (isAudioSystemDevice()) {
+                        if (audioSystem() == null) {
+                            Slog.e(TAG, "Audio System device has not registered yet."
+                                    + " Can't turn system audio mode on.");
+                            break;
+                        }
+                        audioSystem().onSystemAduioControlFeatureSupportChanged(enabled);
+                    }
+                    break;
+                case Global.HDMI_CEC_SWITCH_ENABLED:
+                    if (isAudioSystemDevice()) {
+                        if (audioSystem() == null) {
+                            Slog.w(TAG, "Switch device has not registered yet."
+                                    + " Can't turn routing on.");
+                            break;
+                        }
+                        audioSystem().setRoutingControlFeatureEnables(enabled);
+                    }
                     break;
                 case Global.MHL_INPUT_SWITCHING_ENABLED:
                     setMhlInputChangeEnabled(enabled);
@@ -620,6 +646,7 @@
         return enabled ? ENABLED : DISABLED;
     }
 
+    @VisibleForTesting
     boolean readBooleanSetting(String key, boolean defVal) {
         ContentResolver cr = getContext().getContentResolver();
         return Global.getInt(cr, key, toInt(defVal)) == ENABLED;
@@ -630,6 +657,11 @@
         Global.putInt(cr, key, toInt(value));
     }
 
+    void writeStringSetting(String key, String value) {
+        ContentResolver cr = getContext().getContentResolver();
+        Global.putString(cr, key, value);
+    }
+
     private void initializeCec(int initiatedBy) {
         mAddressAllocated = false;
         mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
@@ -734,6 +766,10 @@
         assertRunOnServiceThread();
         HdmiPortInfo[] cecPortInfo = null;
 
+        synchronized (mLock) {
+            mPhysicalAddress = getPhysicalAddress();
+        }
+
         // CEC HAL provides majority of the info while MHL does only MHL support flag for
         // each port. Return empty array if CEC HAL didn't provide the info.
         if (mCecController != null) {
@@ -827,7 +863,10 @@
     int pathToPortId(int path) {
         int mask = 0xF000;
         int finalMask = 0xF000;
-        int physicalAddress = getPhysicalAddress();
+        int physicalAddress;
+        synchronized (mLock) {
+            physicalAddress = mPhysicalAddress;
+        }
         int maskedAddress = physicalAddress;
 
         while (maskedAddress != 0) {
@@ -1135,7 +1174,7 @@
         String displayName = Build.MODEL;
         return new HdmiDeviceInfo(logicalAddress,
                 getPhysicalAddress(), pathToPortId(getPhysicalAddress()), deviceType,
-                getVendorId(), displayName);
+                getVendorId(), displayName, powerStatus);
     }
 
     @ServiceThreadOnly
@@ -1354,6 +1393,33 @@
             HdmiCecLocalDeviceTv tv = tv();
             if (tv == null) {
                 Slog.w(TAG, "Local tv device not available");
+                if (isPlaybackDevice()) {
+                    // if playback device itself is the active source,
+                    // return its own device info.
+                    if (playback() != null && playback().mIsActiveSource) {
+                        return playback().getDeviceInfo();
+                    }
+                    // Otherwise get the active source and look for it from the device list
+                    ActiveSource activeSource = mActiveSource;
+                    // If the active source is not set yet, return null
+                    if (!activeSource.isValid()) {
+                        return null;
+                    }
+                    if (audioSystem() != null) {
+                        HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
+                        for (HdmiDeviceInfo info : audioSystem.getSafeCecDevicesLocked()) {
+                            if (info.getLogicalAddress() == activeSource.logicalAddress) {
+                                return info;
+                            }
+                        }
+                    }
+                    // If the device info is not in the list yet, return a device info with minimum
+                    // information from mActiveSource.
+                    return new HdmiDeviceInfo(activeSource.logicalAddress,
+                        activeSource.physicalAddress, pathToPortId(activeSource.physicalAddress),
+                        HdmiUtils.getTypeFromAddress(activeSource.logicalAddress), 0,
+                        HdmiUtils.getDefaultDeviceName(activeSource.logicalAddress));
+                }
                 return null;
             }
             ActiveSource activeSource = tv.getActiveSource();
@@ -1532,6 +1598,14 @@
         }
 
         @Override
+        public int getPhysicalAddress() {
+            enforceAccessPermission();
+            synchronized (mLock) {
+                return mPhysicalAddress;
+            }
+        }
+
+        @Override
         public void setSystemAudioMode(final boolean enabled, final IHdmiControlCallback callback) {
             enforceAccessPermission();
             runOnServiceThread(new Runnable() {
@@ -1588,14 +1662,62 @@
         public List<HdmiDeviceInfo> getDeviceList() {
             enforceAccessPermission();
             HdmiCecLocalDeviceTv tv = tv();
-            synchronized (mLock) {
-                return (tv == null)
+            if (tv != null) {
+                synchronized (mLock) {
+                    return tv.getSafeCecDevicesLocked();
+                }
+            } else {
+                HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
+                synchronized (mLock) {
+                    return (audioSystem == null)
                         ? Collections.<HdmiDeviceInfo>emptyList()
-                        : tv.getSafeCecDevicesLocked();
+                        : audioSystem.getSafeCecDevicesLocked();
+                }
             }
         }
 
         @Override
+        public void powerOffRemoteDevice(int logicalAddress, int powerStatus) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    Slog.w(TAG, "Device "
+                            + logicalAddress + " power status is " + powerStatus
+                            + " before standby command sent out");
+                    sendCecCommand(HdmiCecMessageBuilder.buildStandby(
+                            getRemoteControlSourceAddress(), logicalAddress));
+                }
+            });
+        }
+
+        @Override
+        public void powerOnRemoteDevice(int logicalAddress, int powerStatus) {
+            // TODO(amyjojo): implement the method
+        }
+
+        @Override
+        // TODO(AMYJOJO): add a result callback
+        public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    HdmiCecMessage setStreamPath = HdmiCecMessageBuilder.buildSetStreamPath(
+                            getRemoteControlSourceAddress(), physicalAddress);
+                    if (pathToPortId(physicalAddress) != Constants.INVALID_PORT_ID) {
+                        if (getSwitchDevice() != null) {
+                            getSwitchDevice().handleSetStreamPath(setStreamPath);
+                        } else {
+                            Slog.e(TAG, "Can't get the correct local device to handle routing.");
+                        }
+                    }
+                    sendCecCommand(setStreamPath);
+                }
+            });
+        }
+
+        @Override
         public void setSystemAudioVolume(final int oldIndex, final int newIndex,
                 final int maxIndex) {
             enforceAccessPermission();
@@ -1834,14 +1956,32 @@
                         Slog.w(TAG, "audio system is not in system audio mode");
                         return;
                     }
-                    int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
+                    audioSystem().reportAudioStatus(Constants.ADDR_TV);
+                }
+            });
+        }
 
-                    sendCecCommand(HdmiCecMessageBuilder
-                            .buildReportAudioStatus(
-                                    device.getDeviceInfo().getLogicalAddress(),
-                                    Constants.ADDR_TV,
-                                    scaledVolume,
-                                    isMute));
+        @Override
+        public void setSystemAudioModeOnForAudioOnlySource() {
+            enforceAccessPermission();
+            runOnServiceThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (!isAudioSystemDevice()) {
+                        Slog.e(TAG, "Not an audio system device. Won't set system audio mode on");
+                        return;
+                    }
+                    if (audioSystem() == null) {
+                        Slog.e(TAG, "Audio System local device is not registered");
+                        return;
+                    }
+                    if (!audioSystem().checkSupportAndSetSystemAudioMode(true)) {
+                        Slog.e(TAG, "System Audio Mode is not supported.");
+                        return;
+                    }
+                    sendCecCommand(
+                            HdmiCecMessageBuilder.buildSetSystemAudioMode(
+                                    audioSystem().mAddress, Constants.ADDR_BROADCAST, true));
                 }
             });
         }
@@ -1851,30 +1991,54 @@
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
 
-            pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
             pw.println("mProhibitMode: " + mProhibitMode);
-            if (mCecController != null) {
-                pw.println("mCecController: ");
-                pw.increaseIndent();
-                mCecController.dump(pw);
-                pw.decreaseIndent();
-            }
+            pw.println("mPowerStatus: " + mPowerStatus);
+
+            // System settings
+            pw.println("System_settings:");
+            pw.increaseIndent();
+            pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
+            pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled);
+            pw.decreaseIndent();
 
             pw.println("mMhlController: ");
             pw.increaseIndent();
             mMhlController.dump(pw);
             pw.decreaseIndent();
 
-            pw.println("mPortInfo: ");
-            pw.increaseIndent();
-            for (HdmiPortInfo hdmiPortInfo : mPortInfo) {
-                pw.println("- " + hdmiPortInfo);
+            HdmiUtils.dumpIterable(pw, "mPortInfo:", mPortInfo);
+            if (mCecController != null) {
+                pw.println("mCecController: ");
+                pw.increaseIndent();
+                mCecController.dump(pw);
+                pw.decreaseIndent();
             }
-            pw.decreaseIndent();
-            pw.println("mPowerStatus: " + mPowerStatus);
         }
     }
 
+    // Get the source address to send out commands to devices connected to the current device
+    // when other services interact with HdmiControlService.
+    private int getRemoteControlSourceAddress() {
+        if (isAudioSystemDevice()) {
+            return audioSystem().getDeviceInfo().getLogicalAddress();
+        } else if (isPlaybackDevice()) {
+            return playback().getDeviceInfo().getLogicalAddress();
+        }
+        return ADDR_UNREGISTERED;
+    }
+
+    // Get the switch device to do CEC routing control
+    @Nullable
+    private HdmiCecLocalDeviceSource getSwitchDevice() {
+        if (isAudioSystemDevice()) {
+            return audioSystem();
+        }
+        if (isPlaybackDevice()) {
+            return playback();
+        }
+        return null;
+    }
+
     @ServiceThreadOnly
     private void oneTouchPlay(final IHdmiControlCallback callback) {
         assertRunOnServiceThread();
@@ -2549,14 +2713,14 @@
     // For example, when receiving broadcast messages, all the device types will call this
     // method but only one of them will be the Active Source.
     protected void setAndBroadcastActiveSource(
-            HdmiCecMessage message, int physicalAddress, int deviceType) {
+            int physicalAddress, int deviceType, int source) {
         // If the device has both playback and audio system logical addresses,
         // playback will claim active source. Otherwise audio system will.
         if (deviceType == HdmiDeviceInfo.DEVICE_PLAYBACK) {
             HdmiCecLocalDevicePlayback playback = playback();
             playback.setIsActiveSource(true);
             playback.wakeUpIfActiveSource();
-            playback.maySendActiveSource(message.getSource());
+            playback.maySendActiveSource(source);
             setActiveSource(playback.mAddress, physicalAddress);
         }
 
@@ -2567,7 +2731,7 @@
             } else {
                 audioSystem.setIsActiveSource(true);
                 audioSystem.wakeUpIfActiveSource();
-                audioSystem.maySendActiveSource(message.getSource());
+                audioSystem.maySendActiveSource(source);
                 setActiveSource(audioSystem.mAddress, physicalAddress);
             }
         }
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 2a8117f..e44f1d1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -16,19 +16,35 @@
 
 package com.android.server.hdmi;
 
+import android.annotation.Nullable;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.Xml;
 
+import com.android.internal.util.HexDump;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.hdmi.Constants.AudioCodec;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * Various utilities to handle HDMI CEC messages.
  */
 final class HdmiUtils {
 
+    private static final String TAG = "HdmiUtils";
+
     private static final int[] ADDRESS_TO_TYPE = {
         HdmiDeviceInfo.DEVICE_TV,  // ADDR_TV
         HdmiDeviceInfo.DEVICE_RECORDER,  // ADDR_RECORDER_1
@@ -65,6 +81,12 @@
         "Secondary_TV",
     };
 
+    /**
+     * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
+     */
+    static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1;
+    static final int TARGET_SAME_PHYSICAL_ADDRESS = 0;
+
     private HdmiUtils() { /* cannot be instantiated */ }
 
     /**
@@ -317,4 +339,339 @@
                 info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(),
                 info.getVendorId(), info.getDisplayName(), newPowerStatus);
     }
+
+    /**
+     * Dump a {@link SparseArray} to the print writer.
+     *
+     * <p>The dump is formatted:
+     * <pre>
+     *     name:
+     *        key = value
+     *        key = value
+     *        ...
+     * </pre>
+     */
+    static <T> void dumpSparseArray(IndentingPrintWriter pw, String name,
+            SparseArray<T> sparseArray) {
+        printWithTrailingColon(pw, name);
+        pw.increaseIndent();
+        int size = sparseArray.size();
+        for (int i = 0; i < size; i++) {
+            int key = sparseArray.keyAt(i);
+            T value = sparseArray.get(key);
+            pw.printPair(Integer.toString(key), value);
+            pw.println();
+        }
+        pw.decreaseIndent();
+    }
+
+    private static void printWithTrailingColon(IndentingPrintWriter pw, String name) {
+        pw.println(name.endsWith(":") ? name : name.concat(":"));
+    }
+
+    /**
+     * Dump a {@link Map} to the print writer.
+     *
+     * <p>The dump is formatted:
+     * <pre>
+     *     name:
+     *        key = value
+     *        key = value
+     *        ...
+     * </pre>
+     */
+    static <K, V> void dumpMap(IndentingPrintWriter pw, String name, Map<K, V> map) {
+        printWithTrailingColon(pw, name);
+        pw.increaseIndent();
+        for (Map.Entry<K, V> entry: map.entrySet()) {
+            pw.printPair(entry.getKey().toString(), entry.getValue());
+            pw.println();
+        }
+        pw.decreaseIndent();
+    }
+
+    /**
+     * Dump a {@link Map} to the print writer.
+     *
+     * <p>The dump is formatted:
+     * <pre>
+     *     name:
+     *        value
+     *        value
+     *        ...
+     * </pre>
+     */
+    static <T> void dumpIterable(IndentingPrintWriter pw, String name, Iterable<T> values) {
+        printWithTrailingColon(pw, name);
+        pw.increaseIndent();
+        for (T value : values) {
+            pw.println(value);
+        }
+        pw.decreaseIndent();
+    }
+
+    /**
+     * Method to parse target physical address to the port number on the current device.
+     *
+     * <p>This check assumes target address is valid.
+     *
+     * @param targetPhysicalAddress is the physical address of the target device
+     * @param myPhysicalAddress is the physical address of the current device
+     * @return
+     * If the target device is under the current device, return the port number of current device
+     * that the target device is connected to. This also applies to the devices that are indirectly
+     * connected to the current device.
+     *
+     * <p>If the target device has the same physical address as the current device, return
+     * {@link #TARGET_SAME_PHYSICAL_ADDRESS}.
+     *
+     * <p>If the target device is not under the current device, return
+     * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}.
+     */
+    public static int getLocalPortFromPhysicalAddress(
+            int targetPhysicalAddress, int myPhysicalAddress) {
+        if (myPhysicalAddress == targetPhysicalAddress) {
+            return TARGET_SAME_PHYSICAL_ADDRESS;
+        }
+
+        int mask = 0xF000;
+        int finalMask = 0xF000;
+        int maskedAddress = myPhysicalAddress;
+
+        while (maskedAddress != 0) {
+            maskedAddress = myPhysicalAddress & mask;
+            finalMask |= mask;
+            mask >>= 4;
+        }
+
+        int portAddress = targetPhysicalAddress & finalMask;
+        if ((portAddress & (finalMask << 4)) != myPhysicalAddress) {
+            return TARGET_NOT_UNDER_LOCAL_DEVICE;
+        }
+
+        mask <<= 4;
+        int port = portAddress & mask;
+        while ((port >> 4) != 0) {
+            port >>= 4;
+        }
+        return port;
+    }
+
+    public static class ShortAudioDescriptorXmlParser {
+        // We don't use namespaces
+        private static final String NS = null;
+
+        // return a list of devices config
+        public static List<DeviceConfig> parse(InputStream in)
+                throws XmlPullParserException, IOException {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
+            parser.setInput(in, null);
+            parser.nextTag();
+            return readDevices(parser);
+        }
+
+        private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
+            if (parser.getEventType() != XmlPullParser.START_TAG) {
+                throw new IllegalStateException();
+            }
+            int depth = 1;
+            while (depth != 0) {
+                switch (parser.next()) {
+                    case XmlPullParser.END_TAG:
+                        depth--;
+                        break;
+                    case XmlPullParser.START_TAG:
+                        depth++;
+                        break;
+                }
+            }
+        }
+
+        private static List<DeviceConfig> readDevices(XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            List<DeviceConfig> devices = new ArrayList<>();
+
+            parser.require(XmlPullParser.START_TAG, NS, "config");
+            while (parser.next() != XmlPullParser.END_TAG) {
+                if (parser.getEventType() != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                String name = parser.getName();
+                // Starts by looking for the device tag
+                if (name.equals("device")) {
+                    String deviceType = parser.getAttributeValue(null, "type");
+                    DeviceConfig config = null;
+                    if (deviceType != null) {
+                        config = readDeviceConfig(parser, deviceType);
+                    }
+                    if (config != null) {
+                        devices.add(config);
+                    }
+                } else {
+                    skip(parser);
+                }
+            }
+            return devices;
+        }
+
+        // Processes device tags in the config.
+        @Nullable
+        private static DeviceConfig readDeviceConfig(XmlPullParser parser, String deviceType)
+                throws XmlPullParserException, IOException {
+            List<CodecSad> codecSads = new ArrayList<>();
+            int format;
+            byte[] descriptor;
+
+            parser.require(XmlPullParser.START_TAG, NS, "device");
+            while (parser.next() != XmlPullParser.END_TAG) {
+                if (parser.getEventType() != XmlPullParser.START_TAG) {
+                    continue;
+                }
+                String tagName = parser.getName();
+
+                // Starts by looking for the supportedFormat tag
+                if (tagName.equals("supportedFormat")) {
+                    String codecAttriValue = parser.getAttributeValue(null, "format");
+                    String sadAttriValue = parser.getAttributeValue(null, "descriptor");
+                    format = (codecAttriValue) == null
+                            ? Constants.AUDIO_CODEC_NONE : formatNameToNum(codecAttriValue);
+                    descriptor = readSad(sadAttriValue);
+                    if (format != Constants.AUDIO_CODEC_NONE && descriptor != null) {
+                        codecSads.add(new CodecSad(format, descriptor));
+                    }
+                    parser.nextTag();
+                    parser.require(XmlPullParser.END_TAG, NS, "supportedFormat");
+                } else {
+                    skip(parser);
+                }
+            }
+            if (codecSads.size() == 0) {
+                return null;
+            }
+            return new DeviceConfig(deviceType, codecSads);
+        }
+
+        // Processes sad attribute in the supportedFormat.
+        @Nullable
+        private static byte[] readSad(String sad) {
+            if (sad == null || sad.length() == 0) {
+                return null;
+            }
+            byte[] sadBytes = HexDump.hexStringToByteArray(sad);
+            if (sadBytes.length != 3) {
+                Slog.w(TAG, "SAD byte array length is not 3. Length = " + sadBytes.length);
+                return null;
+            }
+            return sadBytes;
+        }
+
+        @AudioCodec
+        private static int formatNameToNum(String codecAttriValue) {
+            switch (codecAttriValue) {
+                case "AUDIO_FORMAT_NONE":
+                    return Constants.AUDIO_CODEC_NONE;
+                case "AUDIO_FORMAT_LPCM":
+                    return Constants.AUDIO_CODEC_LPCM;
+                case "AUDIO_FORMAT_DD":
+                    return Constants.AUDIO_CODEC_DD;
+                case "AUDIO_FORMAT_MPEG1":
+                    return Constants.AUDIO_CODEC_MPEG1;
+                case "AUDIO_FORMAT_MP3":
+                    return Constants.AUDIO_CODEC_MP3;
+                case "AUDIO_FORMAT_MPEG2":
+                    return Constants.AUDIO_CODEC_MPEG2;
+                case "AUDIO_FORMAT_AAC":
+                    return Constants.AUDIO_CODEC_AAC;
+                case "AUDIO_FORMAT_DTS":
+                    return Constants.AUDIO_CODEC_DTS;
+                case "AUDIO_FORMAT_ATRAC":
+                    return Constants.AUDIO_CODEC_ATRAC;
+                case "AUDIO_FORMAT_ONEBITAUDIO":
+                    return Constants.AUDIO_CODEC_ONEBITAUDIO;
+                case "AUDIO_FORMAT_DDP":
+                    return Constants.AUDIO_CODEC_DDP;
+                case "AUDIO_FORMAT_DTSHD":
+                    return Constants.AUDIO_CODEC_DTSHD;
+                case "AUDIO_FORMAT_TRUEHD":
+                    return Constants.AUDIO_CODEC_TRUEHD;
+                case "AUDIO_FORMAT_DST":
+                    return Constants.AUDIO_CODEC_DST;
+                case "AUDIO_FORMAT_WMAPRO":
+                    return Constants.AUDIO_CODEC_WMAPRO;
+                case "AUDIO_FORMAT_MAX":
+                    return Constants.AUDIO_CODEC_MAX;
+                default:
+                    return Constants.AUDIO_CODEC_NONE;
+            }
+        }
+    }
+
+    // Device configuration of its supported Codecs and their Short Audio Descriptors.
+    public static class DeviceConfig {
+        /** Name of the device. Should be {@link Constants.AudioDevice}. **/
+        public final String name;
+        /** List of a {@link CodecSad}. **/
+        public final List<CodecSad> supportedCodecs;
+
+        public DeviceConfig(String name, List<CodecSad> supportedCodecs) {
+            this.name = name;
+            this.supportedCodecs = supportedCodecs;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof DeviceConfig) {
+                DeviceConfig that = (DeviceConfig) obj;
+                return that.name.equals(this.name)
+                    && that.supportedCodecs.equals(this.supportedCodecs);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(
+                name,
+                supportedCodecs.hashCode());
+        }
+    }
+
+    // Short Audio Descriptor of a specific Codec
+    public static class CodecSad {
+        /** Audio Codec. Should be {@link Constants.AudioCodec}. **/
+        public final int audioCodec;
+        /**
+         * Three-byte Short Audio Descriptor. See HDMI Specification 1.4b CEC 13.15.3 and
+         * ANSI-CTA-861-F-FINAL 7.5.2 Audio Data Block for more details.
+         */
+        public final byte[] sad;
+
+        public CodecSad(int audioCodec, byte[] sad) {
+            this.audioCodec = audioCodec;
+            this.sad = sad;
+        }
+
+        public CodecSad(int audioCodec, String sad) {
+            this.audioCodec = audioCodec;
+            this.sad = HexDump.hexStringToByteArray(sad);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof CodecSad) {
+                CodecSad that = (CodecSad) obj;
+                return that.audioCodec == this.audioCodec
+                    && Arrays.equals(that.sad, this.sad);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(
+                audioCodec,
+                Arrays.hashCode(sad));
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
index 41bf01f8..354d8d1 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java
@@ -92,6 +92,9 @@
         if (source.mService.audioSystem() != null) {
             source = source.mService.audioSystem();
         }
+        if (source.getLocalActivePort() != Constants.CEC_SWITCH_HOME) {
+            source.switchInputOnReceivingNewActivePath(getSourcePath());
+        }
         source.setRoutingPort(Constants.CEC_SWITCH_HOME);
         source.setLocalActivePort(Constants.CEC_SWITCH_HOME);
     }
diff --git a/services/core/java/com/android/server/job/controllers/QuotaController.java b/services/core/java/com/android/server/job/controllers/QuotaController.java
index ac2dbdf..c16d1b4 100644
--- a/services/core/java/com/android/server/job/controllers/QuotaController.java
+++ b/services/core/java/com/android/server/job/controllers/QuotaController.java
@@ -26,7 +26,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
+import android.app.IUidObserver;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
@@ -38,12 +41,14 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -69,6 +74,11 @@
  * bucket, it will be eligible to run. When a job's bucket changes, its new quota is immediately
  * applied to it.
  *
+ * Jobs are throttled while an app is not in a foreground state. All jobs are allowed to run
+ * freely when an app enters the foreground state and are restricted when the app leaves the
+ * foreground state. However, jobs that are started while the app is in the TOP state are not
+ * restricted regardless of the app's state change.
+ *
  * Test: atest com.android.server.job.controllers.QuotaControllerTest
  */
 public final class QuotaController extends StateController {
@@ -97,6 +107,12 @@
             data.put(packageName, obj);
         }
 
+        public void clear() {
+            for (int i = 0; i < mData.size(); ++i) {
+                mData.valueAt(i).clear();
+            }
+        }
+
         /** Removes all the data for the user, if there was any. */
         public void delete(int userId) {
             mData.delete(userId);
@@ -119,6 +135,11 @@
             return null;
         }
 
+        /** @see SparseArray#indexOfKey */
+        public int indexOfKey(int userId) {
+            return mData.indexOfKey(userId);
+        }
+
         /** Returns the userId at the given index. */
         public int keyAt(int index) {
             return mData.keyAt(index);
@@ -294,6 +315,17 @@
     /** Cached calculation results for each app, with the standby buckets as the array indices. */
     private final UserPackageMap<ExecutionStats[]> mExecutionStatsCache = new UserPackageMap<>();
 
+    /** List of UIDs currently in the foreground. */
+    private final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
+
+    /**
+     * List of jobs that started while the UID was in the TOP state. There will be no more than
+     * 16 ({@link JobSchedulerService.MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
+     * fine.
+     */
+    private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>();
+
+    private final ActivityManagerInternal mActivityManagerInternal;
     private final AlarmManager mAlarmManager;
     private final ChargingTracker mChargeTracker;
     private final Handler mHandler;
@@ -343,6 +375,29 @@
                 }
             };
 
+    private final IUidObserver mUidObserver = new IUidObserver.Stub() {
+        @Override
+        public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+            mHandler.obtainMessage(MSG_UID_PROCESS_STATE_CHANGED, uid, procState).sendToTarget();
+        }
+
+        @Override
+        public void onUidGone(int uid, boolean disabled) {
+        }
+
+        @Override
+        public void onUidActive(int uid) {
+        }
+
+        @Override
+        public void onUidIdle(int uid, boolean disabled) {
+        }
+
+        @Override
+        public void onUidCachedChanged(int uid, boolean cached) {
+        }
+    };
+
     /**
      * The rolling window size for each standby bucket. Within each window, an app will have 10
      * minutes to run its jobs.
@@ -363,12 +418,15 @@
     private static final int MSG_CLEAN_UP_SESSIONS = 1;
     /** Check if a package is now within its quota. */
     private static final int MSG_CHECK_PACKAGE = 2;
+    /** Process state for a UID has changed. */
+    private static final int MSG_UID_PROCESS_STATE_CHANGED = 3;
 
     public QuotaController(JobSchedulerService service) {
         super(service);
         mHandler = new QcHandler(mContext.getMainLooper());
         mChargeTracker = new ChargingTracker();
         mChargeTracker.startTracking();
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
         // Set up the app standby bucketing tracker
@@ -376,6 +434,14 @@
                 UsageStatsManagerInternal.class);
         usageStats.addAppIdleStateChangeListener(new StandbyTracker());
 
+        try {
+            ActivityManager.getService().registerUidObserver(mUidObserver,
+                    ActivityManager.UID_OBSERVER_PROCSTATE,
+                    ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, null);
+        } catch (RemoteException e) {
+            // ignored; both services live in system_server
+        }
+
         onConstantsUpdatedLocked();
     }
 
@@ -399,11 +465,15 @@
         if (DEBUG) Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
         final int userId = jobStatus.getSourceUserId();
         final String packageName = jobStatus.getSourcePackageName();
+        final int uid = jobStatus.getSourceUid();
         Timer timer = mPkgTimers.get(userId, packageName);
         if (timer == null) {
-            timer = new Timer(userId, packageName);
+            timer = new Timer(uid, userId, packageName);
             mPkgTimers.add(userId, packageName, timer);
         }
+        if (mActivityManagerInternal.getUidProcessState(uid) == ActivityManager.PROCESS_STATE_TOP) {
+            mTopStartedJobs.add(jobStatus);
+        }
         timer.startTrackingJob(jobStatus);
     }
 
@@ -421,6 +491,7 @@
             if (jobs != null) {
                 jobs.remove(jobStatus);
             }
+            mTopStartedJobs.remove(jobStatus);
         }
     }
 
@@ -511,6 +582,7 @@
             mInQuotaAlarmListeners.delete(userId, packageName);
         }
         mExecutionStatsCache.delete(userId, packageName);
+        mForegroundUids.delete(uid);
     }
 
     @Override
@@ -522,6 +594,20 @@
         mExecutionStatsCache.delete(userId);
     }
 
+    private boolean isUidInForeground(int uid) {
+        if (UserHandle.isCore(uid)) {
+            return true;
+        }
+        synchronized (mLock) {
+            return mForegroundUids.get(uid);
+        }
+    }
+
+    /** @return true if the job was started while the app was in the TOP state. */
+    private boolean isTopStartedJob(@NonNull final JobStatus jobStatus) {
+        return mTopStartedJobs.contains(jobStatus);
+    }
+
     /**
      * Returns an appropriate standby bucket for the job, taking into account any standby
      * exemptions.
@@ -537,9 +623,15 @@
 
     private boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) {
         final int standbyBucket = getEffectiveStandbyBucket(jobStatus);
-        // Jobs for the active app should always be able to run.
-        return jobStatus.uidActive || isWithinQuotaLocked(
-                jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
+        Timer timer = mPkgTimers.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
+        // A job is within quota if one of the following is true:
+        //   1. it was started while the app was in the TOP state
+        //   2. the app is currently in the foreground
+        //   3. the app overall is within its quota
+        return isTopStartedJob(jobStatus)
+                || isUidInForeground(jobStatus.getSourceUid())
+                || isWithinQuotaLocked(
+                      jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
     }
 
     private boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName,
@@ -800,7 +892,7 @@
         final boolean isCharging = mChargeTracker.isCharging();
         if (DEBUG) Slog.d(TAG, "handleNewChargingStateLocked: " + isCharging);
         // Deal with Timers first.
-        mPkgTimers.forEach((t) -> t.onChargingChanged(nowElapsed, isCharging));
+        mPkgTimers.forEach((t) -> t.onStateChanged(nowElapsed, isCharging));
         // Now update jobs.
         maybeUpdateAllConstraintsLocked();
     }
@@ -837,10 +929,15 @@
         boolean changed = false;
         for (int i = jobs.size() - 1; i >= 0; --i) {
             final JobStatus js = jobs.valueAt(i);
-            if (js.uidActive) {
-                // Jobs for the active app should always be able to run.
+            if (isTopStartedJob(js)) {
+                // Job was started while the app was in the TOP state so we should allow it to
+                // finish.
                 changed |= js.setQuotaConstraintSatisfied(true);
-            } else if (realStandbyBucket == getEffectiveStandbyBucket(js)) {
+            } else if (realStandbyBucket != ACTIVE_INDEX
+                    && realStandbyBucket == getEffectiveStandbyBucket(js)) {
+                // An app in the ACTIVE bucket may be out of quota while the job could be in quota
+                // for some reason. Therefore, avoid setting the real value here and check each job
+                // individually.
                 changed |= js.setQuotaConstraintSatisfied(realInQuota);
             } else {
                 // This job is somehow exempted. Need to determine its own quota status.
@@ -854,7 +951,7 @@
             maybeScheduleStartAlarmLocked(userId, packageName, realStandbyBucket);
         } else {
             QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
-            if (alarmListener != null) {
+            if (alarmListener != null && alarmListener.isWaiting()) {
                 mAlarmManager.cancel(alarmListener);
                 // Set the trigger time to 0 so that the alarm doesn't think it's still waiting.
                 alarmListener.setTriggerTime(0);
@@ -863,6 +960,56 @@
         return changed;
     }
 
+    private class UidConstraintUpdater implements Consumer<JobStatus> {
+        private final UserPackageMap<Integer> mToScheduleStartAlarms = new UserPackageMap<>();
+        public boolean wasJobChanged;
+
+        @Override
+        public void accept(JobStatus jobStatus) {
+            wasJobChanged |= jobStatus.setQuotaConstraintSatisfied(isWithinQuotaLocked(jobStatus));
+            final int userId = jobStatus.getSourceUserId();
+            final String packageName = jobStatus.getSourcePackageName();
+            final int realStandbyBucket = jobStatus.getStandbyBucket();
+            if (isWithinQuotaLocked(userId, packageName, realStandbyBucket)) {
+                QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
+                if (alarmListener != null && alarmListener.isWaiting()) {
+                    mAlarmManager.cancel(alarmListener);
+                    // Set the trigger time to 0 so that the alarm doesn't think it's still waiting.
+                    alarmListener.setTriggerTime(0);
+                }
+            } else {
+                mToScheduleStartAlarms.add(userId, packageName, realStandbyBucket);
+            }
+        }
+
+        void postProcess() {
+            for (int u = 0; u < mToScheduleStartAlarms.numUsers(); ++u) {
+                final int userId = mToScheduleStartAlarms.keyAt(u);
+                for (int p = 0; p < mToScheduleStartAlarms.numPackagesForUser(userId); ++p) {
+                    final String packageName = mToScheduleStartAlarms.keyAt(u, p);
+                    final int standbyBucket = mToScheduleStartAlarms.get(userId, packageName);
+                    maybeScheduleStartAlarmLocked(userId, packageName, standbyBucket);
+                }
+            }
+        }
+
+        void reset() {
+            wasJobChanged = false;
+            mToScheduleStartAlarms.clear();
+        }
+    }
+
+    private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
+
+    private boolean maybeUpdateConstraintForUidLocked(final int uid) {
+        mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
+
+        mUpdateUidConstraints.postProcess();
+        boolean changed = mUpdateUidConstraints.wasJobChanged;
+        mUpdateUidConstraints.reset();
+        return changed;
+    }
+
     /**
      * Maybe schedule a non-wakeup alarm for the next time this package will have quota to run
      * again. This should only be called if the package is already out of quota.
@@ -1052,6 +1199,7 @@
 
     private final class Timer {
         private final Package mPkg;
+        private final int mUid;
 
         // List of jobs currently running for this app that started when the app wasn't in the
         // foreground.
@@ -1059,16 +1207,18 @@
         private long mStartTimeElapsed;
         private int mBgJobCount;
 
-        Timer(int userId, String packageName) {
+        Timer(int uid, int userId, String packageName) {
             mPkg = new Package(userId, packageName);
+            mUid = uid;
         }
 
         void startTrackingJob(@NonNull JobStatus jobStatus) {
-            if (jobStatus.uidActive) {
-                // We intentionally don't pay attention to fg state changes after a job has started.
+            if (isTopStartedJob(jobStatus)) {
+                // We intentionally don't pay attention to fg state changes after a TOP job has
+                // started.
                 if (DEBUG) {
                     Slog.v(TAG,
-                            "Timer ignoring " + jobStatus.toShortString() + " because uidActive");
+                            "Timer ignoring " + jobStatus.toShortString() + " because isTop");
                 }
                 return;
             }
@@ -1076,7 +1226,7 @@
             synchronized (mLock) {
                 // Always track jobs, even when charging.
                 mRunningBgJobs.add(jobStatus);
-                if (!mChargeTracker.isCharging()) {
+                if (shouldTrackLocked()) {
                     mBgJobCount++;
                     if (mRunningBgJobs.size() == 1) {
                         // Started tracking the first job.
@@ -1142,6 +1292,10 @@
             }
         }
 
+        boolean isRunning(JobStatus jobStatus) {
+            return mRunningBgJobs.contains(jobStatus);
+        }
+
         long getCurrentDuration(long nowElapsed) {
             synchronized (mLock) {
                 return !isActive() ? 0 : nowElapsed - mStartTimeElapsed;
@@ -1154,17 +1308,21 @@
             }
         }
 
-        void onChargingChanged(long nowElapsed, boolean isCharging) {
+        private boolean shouldTrackLocked() {
+            return !mChargeTracker.isCharging() && !mForegroundUids.get(mUid);
+        }
+
+        void onStateChanged(long nowElapsed, boolean isQuotaFree) {
             synchronized (mLock) {
-                if (isCharging) {
+                if (isQuotaFree) {
                     emitSessionLocked(nowElapsed);
-                } else {
+                } else if (shouldTrackLocked()) {
                     // Start timing from unplug.
                     if (mRunningBgJobs.size() > 0) {
                         mStartTimeElapsed = nowElapsed;
                         // NOTE: this does have the unfortunate consequence that if the device is
-                        // repeatedly plugged in and unplugged, the job count for a package may be
-                        // artificially high.
+                        // repeatedly plugged in and unplugged, or an app changes foreground state
+                        // very frequently, the job count for a package may be artificially high.
                         mBgJobCount = mRunningBgJobs.size();
                         // Starting the timer means that all cached execution stats are now
                         // incorrect.
@@ -1371,6 +1529,38 @@
                         }
                         break;
                     }
+                    case MSG_UID_PROCESS_STATE_CHANGED: {
+                        final int uid = msg.arg1;
+                        final int procState = msg.arg2;
+                        final int userId = UserHandle.getUserId(uid);
+                        final long nowElapsed = sElapsedRealtimeClock.millis();
+
+                        synchronized (mLock) {
+                            boolean isQuotaFree;
+                            if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                                mForegroundUids.put(uid, true);
+                                isQuotaFree = true;
+                            } else {
+                                mForegroundUids.delete(uid);
+                                isQuotaFree = false;
+                            }
+                            // Update Timers first.
+                            final int userIndex = mPkgTimers.indexOfKey(userId);
+                            if (userIndex != -1) {
+                                final int numPkgs = mPkgTimers.numPackagesForUser(userId);
+                                for (int p = 0; p < numPkgs; ++p) {
+                                    Timer t = mPkgTimers.valueAt(userIndex, p);
+                                    if (t != null) {
+                                        t.onStateChanged(nowElapsed, isQuotaFree);
+                                    }
+                                }
+                            }
+                            if (maybeUpdateConstraintForUidLocked(uid)) {
+                                mStateChangedListener.onControllerStateChanged();
+                            }
+                        }
+                        break;
+                    }
                 }
             }
         }
@@ -1420,6 +1610,12 @@
 
     @VisibleForTesting
     @NonNull
+    SparseBooleanArray getForegroundUids() {
+        return mForegroundUids;
+    }
+
+    @VisibleForTesting
+    @NonNull
     Handler getHandler() {
         return mHandler;
     }
@@ -1450,6 +1646,10 @@
         pw.println("In parole: " + mInParole);
         pw.println();
 
+        pw.print("Foreground UIDs: ");
+        pw.println(mForegroundUids.toString());
+        pw.println();
+
         mTrackedJobs.forEach((jobs) -> {
             for (int j = 0; j < jobs.size(); j++) {
                 final JobStatus js = jobs.valueAt(j);
@@ -1460,6 +1660,9 @@
                 js.printUniqueId(pw);
                 pw.print(" from ");
                 UserHandle.formatUid(pw, js.getSourceUid());
+                if (mTopStartedJobs.contains(js)) {
+                    pw.print(" (TOP)");
+                }
                 pw.println();
 
                 pw.increaseIndent();
@@ -1511,6 +1714,11 @@
         proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
         proto.write(StateControllerProto.QuotaController.IS_IN_PAROLE, mInParole);
 
+        for (int i = 0; i < mForegroundUids.size(); ++i) {
+            proto.write(StateControllerProto.QuotaController.FOREGROUND_UIDS,
+                    mForegroundUids.keyAt(i));
+        }
+
         mTrackedJobs.forEach((jobs) -> {
             for (int j = 0; j < jobs.size(); j++) {
                 final JobStatus js = jobs.valueAt(j);
@@ -1526,6 +1734,8 @@
                 proto.write(
                         StateControllerProto.QuotaController.TrackedJob.EFFECTIVE_STANDBY_BUCKET,
                         getEffectiveStandbyBucket(js));
+                proto.write(StateControllerProto.QuotaController.TrackedJob.IS_TOP_STARTED_JOB,
+                        mTopStartedJobs.contains(js));
                 proto.write(StateControllerProto.QuotaController.TrackedJob.HAS_QUOTA,
                         js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
                 proto.write(StateControllerProto.QuotaController.TrackedJob.REMAINING_QUOTA_MS,
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index 29465ad..9e33943 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -29,7 +29,10 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
@@ -66,6 +69,7 @@
             "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL";
     private static final String CONFIG_GPS_LOCK = "GPS_LOCK";
     private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC";
+    public static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS";
 
     // Limit on NI emergency mode time extension after emergency sessions ends
     private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300;  // 5 minute maximum
@@ -171,6 +175,32 @@
     }
 
     /**
+     * Returns the list of proxy apps from the value of config parameter NFW_PROXY_APPS or
+     * {@Collections.EMPTY_LIST} if no value is provided.
+     */
+    List<String> getProxyApps() {
+        // Space separated list of Android proxy app package names.
+        String proxyAppsStr = mProperties.getProperty(CONFIG_NFW_PROXY_APPS);
+        if (TextUtils.isEmpty(proxyAppsStr)) {
+            return Collections.EMPTY_LIST;
+        }
+
+        String[] proxyAppsArray = proxyAppsStr.trim().split("\\s+");
+        if (proxyAppsArray.length == 0) {
+            return Collections.EMPTY_LIST;
+        }
+
+        // TODO(b/122856486): Validate proxy app names so that a system app or some popular app
+        //                    with location permission is not specified as a proxy app.
+        ArrayList proxyApps = new ArrayList(proxyAppsArray.length);
+        for (String proxyApp : proxyAppsArray) {
+            proxyApps.add(proxyApp);
+        }
+
+        return proxyApps;
+    }
+
+    /**
      * Updates the GNSS HAL satellite blacklist.
      */
     void setSatelliteBlacklist(int[] constellations, int[] svids) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index dfb98c3..d346ddc 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -372,6 +372,7 @@
     private boolean mSuplEsEnabled = false;
 
     private final Context mContext;
+    private final Looper mLooper;
     private final LocationExtras mLocationExtras = new LocationExtras();
     private final GnssStatusListenerHelper mGnssStatusListenerHelper;
     private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper;
@@ -382,6 +383,7 @@
     private final NtpTimeHelper mNtpTimeHelper;
     private final GnssBatchingProvider mGnssBatchingProvider;
     private final GnssGeofenceProvider mGnssGeofenceProvider;
+    private GnssVisibilityControl mGnssVisibilityControl;
 
     // Handler for processing events
     private Handler mHandler;
@@ -556,6 +558,9 @@
         mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT);
         mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec());
         mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1;
+        if (mGnssVisibilityControl != null) {
+            mGnssVisibilityControl.updateProxyApps(mGnssConfiguration.getProxyApps());
+        }
     }
 
     public GnssLocationProvider(Context context, LocationProviderManager locationProviderManager,
@@ -563,6 +568,7 @@
         super(locationProviderManager);
 
         mContext = context;
+        mLooper = looper;
 
         // Create a wake lock
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -1869,6 +1875,27 @@
         }
     }
 
+    // Implements method nfwNotifyCb() in IGnssVisibilityControlCallback.hal.
+    @NativeEntryPoint
+    private void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
+            String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
+            boolean inEmergencyMode, boolean isCachedLocation) {
+        if (mGnssVisibilityControl == null) {
+            Log.e(TAG, "reportNfwNotification: mGnssVisibilityControl is not initialized.");
+            return;
+        }
+
+        mGnssVisibilityControl.reportNfwNotification(proxyAppPackageName, protocolStack,
+                otherProtocolStackName, requestor, requestorId, responseType, inEmergencyMode,
+                isCachedLocation);
+    }
+
+    // Implements method isInEmergencySession() in IGnssVisibilityControlCallback.hal.
+    @NativeEntryPoint
+    boolean isInEmergencySession() {
+        return mNIHandler.getInEmergency();
+    }
+
     private void sendMessage(int message, int arg, Object obj) {
         // hold a wake lock until this message is delivered
         // note that this assumes the message will not be removed from the queue before
@@ -1957,6 +1984,10 @@
                 native_cleanup();
             }
 
+            if (native_is_gnss_visibility_control_supported()) {
+                mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper);
+            }
+
             // load default GPS configuration
             // (this configuration might change in the future based on SIM changes)
             reloadGpsProperties();
@@ -2114,6 +2145,8 @@
 
     private static native boolean native_is_supported();
 
+    private static native boolean native_is_gnss_visibility_control_supported();
+
     private static native void native_init_once();
 
     private native boolean native_init();
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
new file mode 100644
index 0000000..845aa9d
--- /dev/null
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import android.annotation.SuppressLint;
+import android.app.AppOpsManager;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Handles GNSS non-framework location access user visibility and control.
+ *
+ * The state of the GnssVisibilityControl object must be accessed/modified through the Handler
+ * thread only.
+ */
+class GnssVisibilityControl {
+    private static final String TAG = "GnssVisibilityControl";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    // Constants related to non-framework (NFW) location access permission proxy apps.
+    private static final String NFW_PROXY_APP_PKG_ACTIVITY_NAME_SUFFIX =
+            ".NonFrameworkLocationAccessActivity";
+    private static final String NFW_INTENT_ACTION_NFW_LOCATION_ACCESS_SUFFIX =
+            ".intent.action.NON_FRAMEWORK_LOCATION_ACCESS";
+    private static final String NFW_INTENT_TYPE = "text/plain";
+
+    private static final String LOCATION_PERMISSION_NAME =
+            "android.permission.ACCESS_FINE_LOCATION";
+
+    // Wakelocks
+    private static final String WAKELOCK_KEY = TAG;
+    private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
+    private final PowerManager.WakeLock mWakeLock;
+
+    private final AppOpsManager mAppOps;
+    private final PackageManager mPackageManager;
+
+    private final Handler mHandler;
+    private final Context mContext;
+
+    // Number of non-framework location access proxy apps is expected to be small (< 5).
+    private static final int HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
+    private HashMap<String, Boolean> mProxyAppToLocationPermissions = new HashMap<>(
+            HASH_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+
+    private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
+            uid -> postEvent(() -> handlePermissionsChanged(uid));
+
+    GnssVisibilityControl(Context context, Looper looper) {
+        mContext = context;
+        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+        mHandler = new Handler(looper);
+        mAppOps = mContext.getSystemService(AppOpsManager.class);
+        mPackageManager = mContext.getPackageManager();
+        // TODO(b/122855984): Handle global location settings on/off.
+        // TODO(b/122856189): Handle roaming case.
+    }
+
+    void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
+        // NOTE: This class doesn't explicitly register and listen for SIM_STATE_CHANGED event
+        //       but rather piggy backs on the GnssLocationProvider SIM_STATE_CHANGED handling
+        //       so that the order of processing is preserved. GnssLocationProvider should
+        //       first load the new config parameters for the new SIM and then call this method.
+        postEvent(() -> handleSubscriptionOrSimChanged(nfwLocationAccessProxyApps));
+    }
+
+    void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
+            String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
+            boolean inEmergencyMode, boolean isCachedLocation) {
+        postEvent(() -> handleNfwNotification(
+                new NfwNotification(proxyAppPackageName, protocolStack, otherProtocolStackName,
+                        requestor, requestorId, responseType, inEmergencyMode, isCachedLocation)));
+    }
+
+    private void handleSubscriptionOrSimChanged(List<String> nfwLocationAccessProxyApps) {
+        if (nfwLocationAccessProxyApps.isEmpty()) {
+            // Stop listening for app permission changes. Clear the app list in GNSS HAL.
+            if (!mProxyAppToLocationPermissions.isEmpty()) {
+                mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
+                mProxyAppToLocationPermissions.clear();
+                updateNfwLocationAccessProxyAppsInGnssHal();
+            }
+            return;
+        }
+
+        if (mProxyAppToLocationPermissions.isEmpty()) {
+            mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
+        } else {
+            mProxyAppToLocationPermissions.clear();
+        }
+
+        for (String proxApp : nfwLocationAccessProxyApps) {
+            mProxyAppToLocationPermissions.put(proxApp, hasLocationPermission(proxApp));
+        }
+
+        updateNfwLocationAccessProxyAppsInGnssHal();
+    }
+
+    // Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
+    private static class NfwNotification {
+        private static final String KEY_PROTOCOL_STACK = "ProtocolStack";
+        private static final String KEY_OTHER_PROTOCOL_STACK_NAME = "OtherProtocolStackName";
+        private static final String KEY_REQUESTOR = "Requestor";
+        private static final String KEY_REQUESTOR_ID = "RequestorId";
+        private static final String KEY_RESPONSE_TYPE = "ResponseType";
+        private static final String KEY_IN_EMERGENCY_MODE = "InEmergencyMode";
+        private static final String KEY_IS_CACHED_LOCATION = "IsCachedLocation";
+
+        // This must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
+        private static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
+        private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
+        private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
+
+        private final String mProxyAppPackageName;
+        private final byte mProtocolStack;
+        private final String mOtherProtocolStackName;
+        private final byte mRequestor;
+        private final String mRequestorId;
+        private final byte mResponseType;
+        private final boolean mInEmergencyMode;
+        private final boolean mIsCachedLocation;
+
+        NfwNotification(String proxyAppPackageName, byte protocolStack,
+                String otherProtocolStackName, byte requestor, String requestorId,
+                byte responseType, boolean inEmergencyMode, boolean isCachedLocation) {
+            mProxyAppPackageName = proxyAppPackageName;
+            mProtocolStack = protocolStack;
+            mOtherProtocolStackName = otherProtocolStackName;
+            mRequestor = requestor;
+            mRequestorId = requestorId;
+            mResponseType = responseType;
+            mInEmergencyMode = inEmergencyMode;
+            mIsCachedLocation = isCachedLocation;
+        }
+
+        void copyFieldsToIntent(Intent intent) {
+            intent.putExtra(KEY_PROTOCOL_STACK, mProtocolStack);
+            if (!TextUtils.isEmpty(mOtherProtocolStackName)) {
+                intent.putExtra(KEY_OTHER_PROTOCOL_STACK_NAME, mOtherProtocolStackName);
+            }
+            intent.putExtra(KEY_REQUESTOR, mRequestor);
+            if (!TextUtils.isEmpty(mRequestorId)) {
+                intent.putExtra(KEY_REQUESTOR_ID, mRequestorId);
+            }
+            intent.putExtra(KEY_RESPONSE_TYPE, mResponseType);
+            intent.putExtra(KEY_IN_EMERGENCY_MODE, mInEmergencyMode);
+            if (mResponseType == NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED) {
+                intent.putExtra(KEY_IS_CACHED_LOCATION, mIsCachedLocation);
+            }
+        }
+
+        @SuppressLint("DefaultLocale")
+        public String toString() {
+            return String.format(
+                    "[Notification] proxyAppPackageName: %s, protocolStack: %d"
+                            + ", otherProtocolStackName: %s, requestor: %d, requestorId: %s"
+                            + ", responseType: %d, inEmergencyMode: %b, isCachedLocation: %b",
+                    mProxyAppPackageName, mProtocolStack, mOtherProtocolStackName,
+                    mRequestor, mRequestorId, mResponseType, mInEmergencyMode, mIsCachedLocation);
+        }
+
+        String getResponseTypeAsString() {
+            switch (mResponseType) {
+                case NFW_RESPONSE_TYPE_REJECTED:
+                    return "REJECTED";
+                case NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED:
+                    return "ACCEPTED_NO_LOCATION_PROVIDED";
+                case NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED:
+                    return "ACCEPTED_LOCATION_PROVIDED";
+                default:
+                    return "<Unknown>";
+            }
+        }
+    }
+
+    private void handlePermissionsChanged(int uid) {
+        if (mProxyAppToLocationPermissions.isEmpty()) {
+            return;
+        }
+
+        for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+            // Cannot cache uid since the application could be uninstalled and reinstalled.
+            final String proxyApp = entry.getKey();
+            final Integer nfwProxyAppUid = getApplicationUid(proxyApp);
+            if (nfwProxyAppUid == null || nfwProxyAppUid != uid) {
+                continue;
+            }
+
+            final boolean isLocationPermissionEnabled = hasLocationPermission(proxyApp);
+            if (isLocationPermissionEnabled != entry.getValue()) {
+                Log.i(TAG, "Location permission setting is changed to "
+                        + (isLocationPermissionEnabled ? "enabled" : "disabled")
+                        + " for non-framework location access proxy app "
+                        + proxyApp);
+                entry.setValue(isLocationPermissionEnabled);
+                updateNfwLocationAccessProxyAppsInGnssHal();
+                return;
+            }
+        }
+    }
+
+    private Integer getApplicationUid(String pkgName) {
+        try {
+            return mPackageManager.getApplicationInfo(pkgName, 0).uid;
+        } catch (PackageManager.NameNotFoundException e) {
+            if (DEBUG) {
+                Log.d(TAG, "Non-framework location access proxy app "
+                        + pkgName + " is not found.");
+            }
+            return null;
+        }
+    }
+
+    private boolean hasLocationPermission(String pkgName) {
+        return mPackageManager.checkPermission(LOCATION_PERMISSION_NAME, pkgName)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private void updateNfwLocationAccessProxyAppsInGnssHal() {
+        // Get a count of proxy apps with location permission enabled to array creation size.
+        int countLocationPermissionEnabledProxyApps = 0;
+        for (Boolean hasLocationPermissionEnabled : mProxyAppToLocationPermissions.values()) {
+            if (hasLocationPermissionEnabled) {
+                ++countLocationPermissionEnabledProxyApps;
+            }
+        }
+
+        int i = 0;
+        String[] locationPermissionEnabledProxyApps =
+                new String[countLocationPermissionEnabledProxyApps];
+        for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+            final String proxyApp = entry.getKey();
+            final boolean hasLocationPermissionEnabled = entry.getValue();
+            if (hasLocationPermissionEnabled) {
+                locationPermissionEnabledProxyApps[i++] = proxyApp;
+            }
+        }
+
+        String proxyAppsStr = Arrays.toString(locationPermissionEnabledProxyApps);
+        Log.i(TAG, "Updating non-framework location access proxy apps in the GNSS HAL to: "
+                + proxyAppsStr);
+        boolean result = native_enable_nfw_location_access(locationPermissionEnabledProxyApps);
+        if (!result) {
+            Log.e(TAG, "Failed to update non-framework location access proxy apps in the"
+                    + " GNSS HAL to: " + proxyAppsStr);
+        }
+    }
+
+    private void handleNfwNotification(NfwNotification nfwNotification) {
+        if (DEBUG) Log.d(TAG, nfwNotification.toString());
+
+        final String proxyAppPackageName = nfwNotification.mProxyAppPackageName;
+        if (TextUtils.isEmpty(proxyAppPackageName)) {
+            Log.e(TAG, "ProxyAppPackageName field is not set. Not sending intent to proxy app for "
+                    + nfwNotification);
+            return;
+        }
+
+        Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
+                proxyAppPackageName);
+        if (isLocationPermissionEnabled == null) {
+            // App is not in the configured list.
+            Log.e(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the "
+                    + "value specified for config parameter: "
+                    + GnssConfiguration.CONFIG_NFW_PROXY_APPS + ". Not sending intent to proxy app"
+                    + " for " + nfwNotification);
+            return;
+        }
+
+        // Send intent to non-framework location proxy app with notification information.
+        final Intent intent = new Intent(
+                proxyAppPackageName + NFW_INTENT_ACTION_NFW_LOCATION_ACCESS_SUFFIX);
+        final String proxAppActivityName =
+                proxyAppPackageName + NFW_PROXY_APP_PKG_ACTIVITY_NAME_SUFFIX;
+        intent.setClassName(proxyAppPackageName, proxAppActivityName);
+        intent.setType(NFW_INTENT_TYPE);
+        nfwNotification.copyFieldsToIntent(intent);
+
+        // Check if the proxy app is still installed.
+        final Integer clsAppUid = getApplicationUid(proxyAppPackageName);
+        if (clsAppUid == null || intent.resolveActivity(mPackageManager) == null) {
+            Log.i(TAG, "Proxy application " + proxyAppPackageName + " and/or activity "
+                    + proxAppActivityName + " is not found. Not sending"
+                    + " intent to proxy app for " + nfwNotification);
+            return;
+        }
+
+        // Display location icon attributed to this proxy app.
+        mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, clsAppUid, proxyAppPackageName);
+
+        // Log proxy app permission mismatch between framework and GNSS HAL.
+        boolean isLocationRequestAccepted =
+                nfwNotification.mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED;
+        if (isLocationPermissionEnabled != isLocationRequestAccepted) {
+            Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPackageName
+                    + " location permission is set to " + isLocationPermissionEnabled
+                    + " but GNSS non-framework location access response type is "
+                    + nfwNotification.getResponseTypeAsString() + " for " + nfwNotification);
+        }
+
+        // Notify proxy app.
+        try {
+            if (DEBUG) {
+                Log.d(TAG, "Sending non-framework location access notification intent: " + intent);
+            }
+            mContext.startActivityAsUser(intent, UserHandle.getUserHandleForUid(clsAppUid));
+        } catch (ActivityNotFoundException e) {
+            Log.w(TAG, "Activity not found. Failed to send non-framework location access"
+                    + " notification intent to proxy app activity: " + proxAppActivityName);
+        }
+    }
+
+    private void postEvent(Runnable event) {
+        // Hold a wake lock until this message is delivered.
+        // Note that this assumes the message will not be removed from the queue before
+        // it is handled (otherwise the wake lock would be leaked).
+        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
+        if (!mHandler.post(runEventAndReleaseWakeLock(event))) {
+            mWakeLock.release();
+        }
+    }
+
+    private Runnable runEventAndReleaseWakeLock(Runnable event) {
+        return () -> {
+            try {
+                event.run();
+            } finally {
+                mWakeLock.release();
+            }
+        };
+    }
+
+    private native boolean native_enable_nfw_location_access(String[] proxyApps);
+}
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 86bc9f3..fe91c63 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -52,7 +52,6 @@
         mExtras = null;
 
         setProperties(properties);
-        setEnabled(true);
     }
 
     /** Sets the enabled state of this mock provider. */
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index d611a17..7fffe8e 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -80,7 +80,7 @@
     private final ControllerStub mController;
     private final SessionStub mSession;
     private final SessionCb mSessionCb;
-    private final MediaSessionService mService;
+    private final MediaSessionService.ServiceImpl mService;
     private final Context mContext;
 
     private final Object mLock = new Object();
@@ -120,7 +120,8 @@
     private String mMetadataDescription;
 
     public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
-            SessionCallbackLink cb, String tag, MediaSessionService service, Looper handlerLooper) {
+            SessionCallbackLink cb, String tag, MediaSessionService.ServiceImpl service,
+            Looper handlerLooper) {
         mOwnerPid = ownerPid;
         mOwnerUid = ownerUid;
         mUserId = userId;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index ba7b87e..d20ed8c 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,79 +16,15 @@
 
 package com.android.server.media;
 
-import static android.os.UserHandle.USER_ALL;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
-import android.database.ContentObserver;
-import android.media.AudioManager;
-import android.media.AudioManagerInternal;
-import android.media.AudioPlaybackConfiguration;
-import android.media.AudioSystem;
-import android.media.IAudioService;
-import android.media.IRemoteVolumeController;
-import android.media.MediaController2;
-import android.media.Session2CommandGroup;
 import android.media.Session2Token;
-import android.media.session.IActiveSessionsListener;
-import android.media.session.ICallback;
-import android.media.session.IOnMediaKeyListener;
-import android.media.session.IOnVolumeKeyLongPressListener;
-import android.media.session.ISession;
-import android.media.session.ISession2TokensListener;
-import android.media.session.ISessionManager;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.media.session.SessionCallbackLink;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.IBinder;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.speech.RecognizerIntent;
-import android.text.TextUtils;
 import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-import android.view.KeyEvent;
-import android.view.ViewConfiguration;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.DumpUtils;
-import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.Watchdog;
 import com.android.server.Watchdog.Monitor;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -97,2040 +33,124 @@
 public class MediaSessionService extends SystemService implements Monitor {
     private static final String TAG = "MediaSessionService";
     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    // Leave log for key event always.
-    private static final boolean DEBUG_KEY_EVENT = true;
 
-    private static final int WAKELOCK_TIMEOUT = 5000;
-    private static final int MEDIA_KEY_LISTENER_TIMEOUT = 1000;
-
-    private final SessionManagerImpl mSessionManagerImpl;
-    private final MessageHandler mHandler = new MessageHandler();
-    private final PowerManager.WakeLock mMediaEventWakeLock;
-    private final int mLongPressTimeout;
-    private final INotificationManager mNotificationManager;
-    private final Object mLock = new Object();
-    // Keeps the full user id for each user.
-    @GuardedBy("mLock")
-    private final SparseIntArray mFullUserIds = new SparseIntArray();
-    @GuardedBy("mLock")
-    private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<FullUserRecord>();
-    @GuardedBy("mLock")
-    private final ArrayList<SessionsListenerRecord> mSessionsListeners
-            = new ArrayList<SessionsListenerRecord>();
-    // Map user id as index to list of Session2Tokens
-    // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in
-    //       one place.
-    @GuardedBy("mLock")
-    private final SparseArray<List<Session2Token>> mSession2TokensPerUser = new SparseArray<>();
-    @GuardedBy("mLock")
-    private final List<Session2TokensListenerRecord> mSession2TokensListenerRecords =
-            new ArrayList<>();
-
-    private KeyguardManager mKeyguardManager;
-    private IAudioService mAudioService;
-    private AudioManagerInternal mAudioManagerInternal;
-    private ActivityManager mActivityManager;
-    private ContentResolver mContentResolver;
-    private SettingsObserver mSettingsObserver;
-    private boolean mHasFeatureLeanback;
-
-    // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
-    // It's always not null after the MediaSessionService is started.
-    private FullUserRecord mCurrentFullUserRecord;
-    private MediaSessionRecord mGlobalPrioritySession;
-    private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
-
-    // Used to notify system UI when remote volume was changed. TODO find a
-    // better way to handle this.
-    private IRemoteVolumeController mRvc;
+    private final ServiceImpl mImpl;
 
     public MediaSessionService(Context context) {
         super(context);
-        mSessionManagerImpl = new SessionManagerImpl();
-        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
-        mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
-        mNotificationManager = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        mImpl = new MediaSessionServiceImpl(context);
     }
 
     @Override
     public void onStart() {
-        publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
+        publishBinderService(Context.MEDIA_SESSION_SERVICE, mImpl.getServiceBinder());
         Watchdog.getInstance().addMonitor(this);
-        mKeyguardManager =
-                (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
-        mAudioService = getAudioService();
-        mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
-        mActivityManager =
-                (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
-        mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance();
-        mAudioPlayerStateMonitor.registerListener(
-                (config, isRemoved) -> {
-                    if (isRemoved || !config.isActive() || config.getPlayerType()
-                            == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
-                        return;
-                    }
-                    synchronized (mLock) {
-                        FullUserRecord user = getFullUserRecordLocked(
-                                UserHandle.getUserId(config.getClientUid()));
-                        if (user != null) {
-                            user.mPriorityStack.updateMediaButtonSessionIfNeeded();
-                        }
-                    }
-                }, null /* handler */);
-        mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);
-        mContentResolver = getContext().getContentResolver();
-        mSettingsObserver = new SettingsObserver();
-        mSettingsObserver.observe();
-        mHasFeatureLeanback = getContext().getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_LEANBACK);
 
-        updateUser();
+        mImpl.onStart();
     }
 
-    private IAudioService getAudioService() {
-        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
-        return IAudioService.Stub.asInterface(b);
+    @Override
+    public void onStartUser(int userId) {
+        mImpl.onStartUser(userId);
     }
 
-    private boolean isGlobalPriorityActiveLocked() {
-        return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive();
+    @Override
+    public void onSwitchUser(int userId) {
+        mImpl.onSwitchUser(userId);
     }
 
+    // Called when the user with the userId is removed.
+    @Override
+    public void onStopUser(int userId) {
+        mImpl.onStopUser(userId);
+    }
+
+    @Override
+    public void monitor() {
+        mImpl.monitor();
+    }
+
+    /**
+     * Updates session.
+     */
     public void updateSession(MediaSessionRecord record) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            if (user == null) {
-                Log.w(TAG, "Unknown session updated. Ignoring.");
-                return;
-            }
-            if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
-                if (DEBUG_KEY_EVENT) {
-                    Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
-                }
-                user.pushAddressedPlayerChangedLocked();
-            } else {
-                if (!user.mPriorityStack.contains(record)) {
-                    Log.w(TAG, "Unknown session updated. Ignoring.");
-                    return;
-                }
-                user.mPriorityStack.onSessionStateChange(record);
-            }
-            mHandler.postSessionsChanged(record.getUserId());
-        }
+        mImpl.updateSession(record);
     }
 
+    /**
+     * Sets global priority session.
+     */
     public void setGlobalPrioritySession(MediaSessionRecord record) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            if (mGlobalPrioritySession != record) {
-                Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
-                        + " to " + record);
-                mGlobalPrioritySession = record;
-                if (user != null && user.mPriorityStack.contains(record)) {
-                    // Handle the global priority session separately.
-                    // Otherwise, it can be the media button session regardless of the active state
-                    // because it or other system components might have been the lastly played media
-                    // app.
-                    user.mPriorityStack.removeSession(record);
-                }
-            }
-        }
-    }
-
-    private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
-        List<MediaSessionRecord> records = new ArrayList<>();
-        if (userId == USER_ALL) {
-            int size = mUserRecords.size();
-            for (int i = 0; i < size; i++) {
-                records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
-            }
-        } else {
-            FullUserRecord user = getFullUserRecordLocked(userId);
-            if (user == null) {
-                Log.w(TAG, "getSessions failed. Unknown user " + userId);
-                return records;
-            }
-            records.addAll(user.mPriorityStack.getActiveSessions(userId));
-        }
-
-        // Return global priority session at the first whenever it's asked.
-        if (isGlobalPriorityActiveLocked()
-                && (userId == USER_ALL || userId == mGlobalPrioritySession.getUserId())) {
-            records.add(0, mGlobalPrioritySession);
-        }
-        return records;
+        mImpl.setGlobalPrioritySession(record);
     }
 
     List<Session2Token> getSession2TokensLocked(int userId) {
-        List<Session2Token> list = new ArrayList<>();
-        if (userId == USER_ALL) {
-            for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
-                list.addAll(mSession2TokensPerUser.valueAt(i));
-            }
-        } else {
-            list.addAll(mSession2TokensPerUser.get(userId));
-        }
-        return list;
+        return mImpl.getSession2TokensLocked(userId);
     }
 
     /**
      * Tells the system UI that volume has changed on an active remote session.
      */
     public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
-        if (mRvc == null || !session.isActive()) {
-            return;
-        }
-        try {
-            mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
-        } catch (Exception e) {
-            Log.wtf(TAG, "Error sending volume change to system UI.", e);
-        }
+        mImpl.notifyRemoteVolumeChanged(flags, session);
     }
 
+    /**
+     * Called when session playstate is changed.
+     */
     public void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            if (user == null || !user.mPriorityStack.contains(record)) {
-                Log.d(TAG, "Unknown session changed playback state. Ignoring.");
-                return;
-            }
-            user.mPriorityStack.onPlaystateChanged(record, oldState, newState);
-        }
+        mImpl.onSessionPlaystateChanged(record, oldState, newState);
     }
 
+    /**
+     * Called when session playback type is changed.
+     */
     public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            if (user == null || !user.mPriorityStack.contains(record)) {
-                Log.d(TAG, "Unknown session changed playback type. Ignoring.");
-                return;
-            }
-            pushRemoteVolumeUpdateLocked(record.getUserId());
-        }
-    }
-
-    @Override
-    public void onStartUser(int userId) {
-        if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
-        updateUser();
-    }
-
-    @Override
-    public void onSwitchUser(int userId) {
-        if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
-        updateUser();
-    }
-
-    // Called when the user with the userId is removed.
-    @Override
-    public void onStopUser(int userId) {
-        if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
-        synchronized (mLock) {
-            // TODO: Also handle removing user in updateUser() because adding/switching user is
-            //       handled in updateUser().
-            FullUserRecord user = getFullUserRecordLocked(userId);
-            if (user != null) {
-                if (user.mFullUserId == userId) {
-                    user.destroySessionsForUserLocked(USER_ALL);
-                    mUserRecords.remove(userId);
-                } else {
-                    user.destroySessionsForUserLocked(userId);
-                }
-            }
-            mSession2TokensPerUser.remove(userId);
-            updateUser();
-        }
-    }
-
-    @Override
-    public void monitor() {
-        synchronized (mLock) {
-            // Check for deadlock
-        }
+        mImpl.onSessionPlaybackTypeChanged(record);
     }
 
     protected void enforcePhoneStatePermission(int pid, int uid) {
-        if (getContext().checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Must hold the MODIFY_PHONE_STATE permission.");
-        }
+        mImpl.enforcePhoneStatePermission(pid, uid);
     }
 
     void sessionDied(MediaSessionRecord session) {
-        synchronized (mLock) {
-            destroySessionLocked(session);
-        }
+        mImpl.sessionDied(session);
     }
 
     void destroySession(MediaSessionRecord session) {
-        synchronized (mLock) {
-            destroySessionLocked(session);
-        }
-    }
-
-    private void updateUser() {
-        synchronized (mLock) {
-            UserManager manager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
-            mFullUserIds.clear();
-            List<UserInfo> allUsers = manager.getUsers();
-            if (allUsers != null) {
-                for (UserInfo userInfo : allUsers) {
-                    if (userInfo.isManagedProfile()) {
-                        mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
-                    } else {
-                        mFullUserIds.put(userInfo.id, userInfo.id);
-                        if (mUserRecords.get(userInfo.id) == null) {
-                            mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
-                        }
-                    }
-                    if (mSession2TokensPerUser.get(userInfo.id) == null) {
-                        mSession2TokensPerUser.put(userInfo.id, new ArrayList<>());
-                    }
-                }
-            }
-            // Ensure that the current full user exists.
-            int currentFullUserId = ActivityManager.getCurrentUser();
-            mCurrentFullUserRecord = mUserRecords.get(currentFullUserId);
-            if (mCurrentFullUserRecord == null) {
-                Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
-                mCurrentFullUserRecord = new FullUserRecord(currentFullUserId);
-                mUserRecords.put(currentFullUserId, mCurrentFullUserRecord);
-                if (mSession2TokensPerUser.get(currentFullUserId) == null) {
-                    mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>());
-                }
-            }
-            mFullUserIds.put(currentFullUserId, currentFullUserId);
-        }
-    }
-
-    private void updateActiveSessionListeners() {
-        synchronized (mLock) {
-            for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
-                SessionsListenerRecord listener = mSessionsListeners.get(i);
-                try {
-                    enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
-                            listener.userId);
-                } catch (SecurityException e) {
-                    Log.i(TAG, "ActiveSessionsListener " + listener.componentName
-                            + " is no longer authorized. Disconnecting.");
-                    mSessionsListeners.remove(i);
-                    try {
-                        listener.listener
-                                .onActiveSessionsChanged(new ArrayList<MediaSession.Token>());
-                    } catch (Exception e1) {
-                        // ignore
-                    }
-                }
-            }
-        }
-    }
-
-    /*
-     * When a session is removed several things need to happen.
-     * 1. We need to remove it from the relevant user.
-     * 2. We need to remove it from the priority stack.
-     * 3. We need to remove it from all sessions.
-     * 4. If this is the system priority session we need to clear it.
-     * 5. We need to unlink to death from the cb binder
-     * 6. We need to tell the session to do any final cleanup (onDestroy)
-     */
-    private void destroySessionLocked(MediaSessionRecord session) {
-        if (DEBUG) {
-            Log.d(TAG, "Destroying " + session);
-        }
-        FullUserRecord user = getFullUserRecordLocked(session.getUserId());
-        if (mGlobalPrioritySession == session) {
-            mGlobalPrioritySession = null;
-            if (session.isActive() && user != null) {
-                user.pushAddressedPlayerChangedLocked();
-            }
-        } else {
-            if (user != null) {
-                user.mPriorityStack.removeSession(session);
-            }
-        }
-
-        try {
-            session.getCallback().getBinder().unlinkToDeath(session, 0);
-        } catch (Exception e) {
-            // ignore exceptions while destroying a session.
-        }
-        session.onDestroy();
-        mHandler.postSessionsChanged(session.getUserId());
-    }
-
-    private void enforcePackageName(String packageName, int uid) {
-        if (TextUtils.isEmpty(packageName)) {
-            throw new IllegalArgumentException("packageName may not be empty");
-        }
-        String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
-        final int packageCount = packages.length;
-        for (int i = 0; i < packageCount; i++) {
-            if (packageName.equals(packages[i])) {
-                return;
-            }
-        }
-        throw new IllegalArgumentException("packageName is not owned by the calling process");
-    }
-
-    /**
-     * Checks a caller's authorization to register an IRemoteControlDisplay.
-     * Authorization is granted if one of the following is true:
-     * <ul>
-     * <li>the caller has android.Manifest.permission.MEDIA_CONTENT_CONTROL
-     * permission</li>
-     * <li>the caller's listener is one of the enabled notification listeners
-     * for the caller's user</li>
-     * </ul>
-     */
-    private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
-            int resolvedUserId) {
-        if (isCurrentVolumeController(pid, uid)) return;
-        if (getContext()
-                .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
-                    != PackageManager.PERMISSION_GRANTED
-                && !isEnabledNotificationListener(compName, UserHandle.getUserId(uid),
-                        resolvedUserId)) {
-            throw new SecurityException("Missing permission to control media.");
-        }
-    }
-
-    private boolean isCurrentVolumeController(int pid, int uid) {
-        return getContext().checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
-                pid, uid) == PackageManager.PERMISSION_GRANTED;
-    }
-
-    private void enforceSystemUiPermission(String action, int pid, int uid) {
-        if (!isCurrentVolumeController(pid, uid)) {
-            throw new SecurityException("Only system ui may " + action);
-        }
-    }
-
-    /**
-     * This checks if the component is an enabled notification listener for the
-     * specified user. Enabled components may only operate on behalf of the user
-     * they're running as.
-     *
-     * @param compName The component that is enabled.
-     * @param userId The user id of the caller.
-     * @param forUserId The user id they're making the request on behalf of.
-     * @return True if the component is enabled, false otherwise
-     */
-    private boolean isEnabledNotificationListener(ComponentName compName, int userId,
-            int forUserId) {
-        if (userId != forUserId) {
-            // You may not access another user's content as an enabled listener.
-            return false;
-        }
-        if (DEBUG) {
-            Log.d(TAG, "Checking if enabled notification listener " + compName);
-        }
-        if (compName != null) {
-            try {
-                return mNotificationManager.isNotificationListenerAccessGrantedForUser(
-                        compName, userId);
-            } catch(RemoteException e) {
-                Log.w(TAG, "Dead NotificationManager in isEnabledNotificationListener", e);
-            }
-        }
-        return false;
-    }
-
-    private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
-            String callerPackageName, SessionCallbackLink cb, String tag) throws RemoteException {
-        synchronized (mLock) {
-            return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb, tag);
-        }
-    }
-
-    /*
-     * When a session is created the following things need to happen.
-     * 1. Its callback binder needs a link to death
-     * 2. It needs to be added to all sessions.
-     * 3. It needs to be added to the priority stack.
-     * 4. It needs to be added to the relevant user record.
-     */
-    private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
-            String callerPackageName, SessionCallbackLink cb, String tag) {
-        FullUserRecord user = getFullUserRecordLocked(userId);
-        if (user == null) {
-            Log.wtf(TAG, "Request from invalid user: " +  userId);
-            throw new RuntimeException("Session request from invalid user.");
-        }
-
-        final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
-                callerPackageName, cb, tag, this, mHandler.getLooper());
-        try {
-            cb.getBinder().linkToDeath(session, 0);
-        } catch (RemoteException e) {
-            throw new RuntimeException("Media Session owner died prematurely.", e);
-        }
-
-        user.mPriorityStack.addSession(session);
-        mHandler.postSessionsChanged(userId);
-
-        if (DEBUG) {
-            Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
-        }
-        return session;
-    }
-
-    private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
-        for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
-            if (mSessionsListeners.get(i).listener.asBinder() == listener.asBinder()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private int findIndexOfSession2TokensListenerLocked(ISession2TokensListener listener) {
-        for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
-            if (mSession2TokensListenerRecords.get(i).listener.asBinder() == listener.asBinder()) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-
-    private void pushSessionsChanged(int userId) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(userId);
-            if (user == null) {
-                Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
-                return;
-            }
-            List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
-            int size = records.size();
-            ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
-            for (int i = 0; i < size; i++) {
-                tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
-            }
-            pushRemoteVolumeUpdateLocked(userId);
-            for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
-                SessionsListenerRecord record = mSessionsListeners.get(i);
-                if (record.userId == USER_ALL || record.userId == userId) {
-                    try {
-                        record.listener.onActiveSessionsChanged(tokens);
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Dead ActiveSessionsListener in pushSessionsChanged, removing",
-                                e);
-                        mSessionsListeners.remove(i);
-                    }
-                }
-            }
-        }
-    }
-
-    private void pushRemoteVolumeUpdateLocked(int userId) {
-        if (mRvc != null) {
-            try {
-                FullUserRecord user = getFullUserRecordLocked(userId);
-                if (user == null) {
-                    Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
-                    return;
-                }
-                MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
-                mRvc.updateRemoteController(record == null ? null : record.getControllerBinder());
-            } catch (RemoteException e) {
-                Log.wtf(TAG, "Error sending default remote volume to sys ui.", e);
-            }
-        }
+        mImpl.destroySession(session);
     }
 
     void pushSession2TokensChangedLocked(int userId) {
-        List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
-        List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
-
-        for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
-            Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
-            try {
-                if (listenerRecord.userId == USER_ALL) {
-                    listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
-                } else if (listenerRecord.userId == userId) {
-                    listenerRecord.listener.onSession2TokensChanged(session2Tokens);
-                }
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
-                mSession2TokensListenerRecords.remove(i);
-            }
-        }
+        mImpl.pushSession2TokensChangedLocked(userId);
     }
 
     /**
-     * Called when the media button receiver for the {@param record} is changed.
-     *
-     * @param record the media session whose media button receiver is updated.
+     * Called when media button receiver changed.
      */
     public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
-        synchronized (mLock) {
-            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            MediaSessionRecord mediaButtonSession =
-                    user.mPriorityStack.getMediaButtonSession();
-            if (record == mediaButtonSession) {
-                user.rememberMediaButtonReceiverLocked(mediaButtonSession);
-            }
-        }
+        mImpl.onMediaButtonReceiverChanged(record);
     }
 
-    private String getCallingPackageName(int uid) {
-        String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
-        if (packages != null && packages.length > 0) {
-            return packages[0];
-        }
-        return "";
-    }
-
-    private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
-        if (mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
-            return;
-        }
-        try {
-            mCurrentFullUserRecord.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
-        }
-    }
-
-    private FullUserRecord getFullUserRecordLocked(int userId) {
-        int fullUserId = mFullUserIds.get(userId, -1);
-        if (fullUserId < 0) {
-            return null;
-        }
-        return mUserRecords.get(fullUserId);
-    }
-
-    /**
-     * Information about a full user and its corresponding managed profiles.
-     *
-     * <p>Since the full user runs together with its managed profiles, a user wouldn't differentiate
-     * them when he/she presses a media/volume button. So keeping media sessions for them in one
-     * place makes more sense and increases the readability.</p>
-     * <p>The contents of this object is guarded by {@link #mLock}.
-     */
-    final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
-        public static final int COMPONENT_TYPE_INVALID = 0;
-        public static final int COMPONENT_TYPE_BROADCAST = 1;
-        public static final int COMPONENT_TYPE_ACTIVITY = 2;
-        public static final int COMPONENT_TYPE_SERVICE = 3;
-        private static final String COMPONENT_NAME_USER_ID_DELIM = ",";
-
-        private final int mFullUserId;
-        private final MediaSessionStack mPriorityStack;
-        private PendingIntent mLastMediaButtonReceiver;
-        private ComponentName mRestoredMediaButtonReceiver;
-        private int mRestoredMediaButtonReceiverComponentType;
-        private int mRestoredMediaButtonReceiverUserId;
-
-        private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener;
-        private int mOnVolumeKeyLongPressListenerUid;
-        private KeyEvent mInitialDownVolumeKeyEvent;
-        private int mInitialDownVolumeStream;
-        private boolean mInitialDownMusicOnly;
-
-        private IOnMediaKeyListener mOnMediaKeyListener;
-        private int mOnMediaKeyListenerUid;
-        private ICallback mCallback;
-
-        public FullUserRecord(int fullUserId) {
-            mFullUserId = fullUserId;
-            mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
-            // Restore the remembered media button receiver before the boot.
-            String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
-                    Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
-            if (mediaButtonReceiverInfo == null) {
-                return;
-            }
-            String[] tokens = mediaButtonReceiverInfo.split(COMPONENT_NAME_USER_ID_DELIM);
-            if (tokens == null || (tokens.length != 2 && tokens.length != 3)) {
-                return;
-            }
-            mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]);
-            mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]);
-            if (tokens.length == 3) {
-                mRestoredMediaButtonReceiverComponentType = Integer.parseInt(tokens[2]);
-            } else {
-                mRestoredMediaButtonReceiverComponentType =
-                        getComponentType(mRestoredMediaButtonReceiver);
-            }
-        }
-
-        public void destroySessionsForUserLocked(int userId) {
-            List<MediaSessionRecord> sessions = mPriorityStack.getPriorityList(false, userId);
-            for (MediaSessionRecord session : sessions) {
-                MediaSessionService.this.destroySessionLocked(session);
-            }
-        }
-
-        public void dumpLocked(PrintWriter pw, String prefix) {
-            pw.print(prefix + "Record for full_user=" + mFullUserId);
-            // Dump managed profile user ids associated with this user.
-            int size = mFullUserIds.size();
-            for (int i = 0; i < size; i++) {
-                if (mFullUserIds.keyAt(i) != mFullUserIds.valueAt(i)
-                        && mFullUserIds.valueAt(i) == mFullUserId) {
-                    pw.print(", profile_user=" + mFullUserIds.keyAt(i));
-                }
-            }
-            pw.println();
-            String indent = prefix + "  ";
-            pw.println(indent + "Volume key long-press listener: " + mOnVolumeKeyLongPressListener);
-            pw.println(indent + "Volume key long-press listener package: " +
-                    getCallingPackageName(mOnVolumeKeyLongPressListenerUid));
-            pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
-            pw.println(indent + "Media key listener package: " +
-                    getCallingPackageName(mOnMediaKeyListenerUid));
-            pw.println(indent + "Callback: " + mCallback);
-            pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
-            pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
-            pw.println(indent + "Restored MediaButtonReceiverComponentType: "
-                    + mRestoredMediaButtonReceiverComponentType);
-            mPriorityStack.dump(pw, indent);
-            pw.println(indent + "Session2Tokens:");
-            for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
-                List<Session2Token> list = mSession2TokensPerUser.valueAt(i);
-                if (list == null || list.size() == 0) {
-                    continue;
-                }
-                for (Session2Token token : list) {
-                    pw.println(indent + "  " + token);
-                }
-            }
-        }
-
-        @Override
-        public void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
-                MediaSessionRecord newMediaButtonSession) {
-            if (DEBUG_KEY_EVENT) {
-                Log.d(TAG, "Media button session is changed to " + newMediaButtonSession);
-            }
-            synchronized (mLock) {
-                if (oldMediaButtonSession != null) {
-                    mHandler.postSessionsChanged(oldMediaButtonSession.getUserId());
-                }
-                if (newMediaButtonSession != null) {
-                    rememberMediaButtonReceiverLocked(newMediaButtonSession);
-                    mHandler.postSessionsChanged(newMediaButtonSession.getUserId());
-                }
-                pushAddressedPlayerChangedLocked();
-            }
-        }
-
-        // Remember media button receiver and keep it in the persistent storage.
-        public void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
-            PendingIntent receiver = record.getMediaButtonReceiver();
-            mLastMediaButtonReceiver = receiver;
-            mRestoredMediaButtonReceiver = null;
-            mRestoredMediaButtonReceiverComponentType = COMPONENT_TYPE_INVALID;
-
-            String mediaButtonReceiverInfo = "";
-            if (receiver != null) {
-                ComponentName component = receiver.getIntent().getComponent();
-                if (component != null
-                        && record.getPackageName().equals(component.getPackageName())) {
-                    String componentName = component.flattenToString();
-                    int componentType = getComponentType(component);
-                    mediaButtonReceiverInfo = String.join(COMPONENT_NAME_USER_ID_DELIM,
-                            componentName, String.valueOf(record.getUserId()),
-                            String.valueOf(componentType));
-                }
-            }
-            Settings.Secure.putStringForUser(mContentResolver,
-                    Settings.System.MEDIA_BUTTON_RECEIVER, mediaButtonReceiverInfo,
-                    mFullUserId);
-        }
-
-        private void pushAddressedPlayerChangedLocked() {
-            if (mCallback == null) {
-                return;
-            }
-            try {
-                MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
-                if (mediaButtonSession != null) {
-                    mCallback.onAddressedPlayerChangedToMediaSession(
-                            new MediaSession.Token(mediaButtonSession.getControllerBinder()));
-                } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
-                            mCurrentFullUserRecord.mLastMediaButtonReceiver
-                                    .getIntent().getComponent());
-                } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
-                            mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
-                }
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
-            }
-        }
-
-        private MediaSessionRecord getMediaButtonSessionLocked() {
-            return isGlobalPriorityActiveLocked()
-                    ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
-        }
-
-        private int getComponentType(@Nullable ComponentName componentName) {
-            if (componentName == null) {
-                return COMPONENT_TYPE_INVALID;
-            }
-            PackageManager pm = getContext().getPackageManager();
-            try {
-                ActivityInfo activityInfo = pm.getActivityInfo(componentName,
-                        PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                                | PackageManager.GET_ACTIVITIES);
-                if (activityInfo != null) {
-                    return COMPONENT_TYPE_ACTIVITY;
-                }
-            } catch (NameNotFoundException e) {
-            }
-            try {
-                ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
-                        PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                                | PackageManager.GET_SERVICES);
-                if (serviceInfo != null) {
-                    return COMPONENT_TYPE_SERVICE;
-                }
-            } catch (NameNotFoundException e) {
-            }
-            // Pick legacy behavior for BroadcastReceiver or unknown.
-            return COMPONENT_TYPE_BROADCAST;
-        }
-    }
-
-    final class SessionsListenerRecord implements IBinder.DeathRecipient {
-        public final IActiveSessionsListener listener;
-        public final ComponentName componentName;
-        public final int userId;
-        public final int pid;
-        public final int uid;
-
-        public SessionsListenerRecord(IActiveSessionsListener listener,
-                ComponentName componentName,
-                int userId, int pid, int uid) {
-            this.listener = listener;
-            this.componentName = componentName;
-            this.userId = userId;
-            this.pid = pid;
-            this.uid = uid;
-        }
-
-        @Override
-        public void binderDied() {
-            synchronized (mLock) {
-                mSessionsListeners.remove(this);
-            }
-        }
-    }
-
-    final class Session2TokensListenerRecord implements IBinder.DeathRecipient {
-        public final ISession2TokensListener listener;
-        public final int userId;
-
-        Session2TokensListenerRecord(ISession2TokensListener listener,
-                int userId) {
-            this.listener = listener;
-            this.userId = userId;
-        }
-
-        @Override
-        public void binderDied() {
-            synchronized (mLock) {
-                mSession2TokensListenerRecords.remove(this);
-            }
-        }
-    }
-
-    final class SettingsObserver extends ContentObserver {
-        private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(
-                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
-
-        private SettingsObserver() {
-            super(null);
-        }
-
-        private void observe() {
-            mContentResolver.registerContentObserver(mSecureSettingsUri,
-                    false, this, USER_ALL);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            updateActiveSessionListeners();
-        }
-    }
-
-    class SessionManagerImpl extends ISessionManager.Stub {
-        private static final String EXTRA_WAKELOCK_ACQUIRED =
-                "android.media.AudioService.WAKELOCK_ACQUIRED";
-        private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
-
-        private boolean mVoiceButtonDown = false;
-        private boolean mVoiceButtonHandled = false;
-
-        @Override
-        public ISession createSession(String packageName, SessionCallbackLink cb, String tag,
-                int userId) throws RemoteException {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                enforcePackageName(packageName, uid);
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        false /* allowAll */, true /* requireFull */, "createSession", packageName);
-                if (cb == null) {
-                    throw new IllegalArgumentException("Controller callback cannot be null");
-                }
-                return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag)
-                        .getSessionBinder();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void notifySession2Created(Session2Token sessionToken) throws RemoteException {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "Session2 is created " + sessionToken);
-                }
-                if (uid != sessionToken.getUid()) {
-                    throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
-                            + " but actually=" + sessionToken.getUid());
-                }
-                Controller2Callback callback = new Controller2Callback(sessionToken);
-                // Note: It's safe not to keep controller here because it wouldn't be GC'ed until
-                //       it's closed.
-                // TODO: Keep controller as well for better readability
-                //       because the GC behavior isn't straightforward.
-                MediaController2 controller = new MediaController2(getContext(), sessionToken,
-                        new HandlerExecutor(mHandler), callback);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public List<IBinder> getSessions(ComponentName componentName, int userId) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
-                ArrayList<IBinder> binders = new ArrayList<IBinder>();
-                synchronized (mLock) {
-                    List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
-                    for (MediaSessionRecord record : records) {
-                        binders.add(record.getControllerBinder().asBinder());
-                    }
-                }
-                return binders;
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public List<Session2Token> getSession2Tokens(int userId) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                // Check that they can make calls on behalf of the user and
-                // get the final user id
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        true /* allowAll */, true /* requireFull */, "getSession2Tokens",
-                        null /* optional packageName */);
-                List<Session2Token> result;
-                synchronized (mLock) {
-                    result = getSession2TokensLocked(resolvedUserId);
-                }
-                return result;
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void addSessionsListener(IActiveSessionsListener listener,
-                ComponentName componentName, int userId) throws RemoteException {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
-                synchronized (mLock) {
-                    int index = findIndexOfSessionsListenerLocked(listener);
-                    if (index != -1) {
-                        Log.w(TAG, "ActiveSessionsListener is already added, ignoring");
-                        return;
-                    }
-                    SessionsListenerRecord record = new SessionsListenerRecord(listener,
-                            componentName, resolvedUserId, pid, uid);
-                    try {
-                        listener.asBinder().linkToDeath(record, 0);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "ActiveSessionsListener is dead, ignoring it", e);
-                        return;
-                    }
-                    mSessionsListeners.add(record);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void removeSessionsListener(IActiveSessionsListener listener)
-                throws RemoteException {
-            synchronized (mLock) {
-                int index = findIndexOfSessionsListenerLocked(listener);
-                if (index != -1) {
-                    SessionsListenerRecord record = mSessionsListeners.remove(index);
-                    try {
-                        record.listener.asBinder().unlinkToDeath(record, 0);
-                    } catch (Exception e) {
-                        // ignore exceptions, the record is being removed
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void addSession2TokensListener(ISession2TokensListener listener,
-                int userId) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                // Check that they can make calls on behalf of the user and get the final user id.
-                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                        true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
-                        null /* optional packageName */);
-                synchronized (mLock) {
-                    int index = findIndexOfSession2TokensListenerLocked(listener);
-                    if (index >= 0) {
-                        Log.w(TAG, "addSession2TokensListener is already added, ignoring");
-                        return;
-                    }
-                    mSession2TokensListenerRecords.add(
-                            new Session2TokensListenerRecord(listener, resolvedUserId));
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void removeSession2TokensListener(ISession2TokensListener listener) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            try {
-                synchronized (mLock) {
-                    int index = findIndexOfSession2TokensListenerLocked(listener);
-                    if (index >= 0) {
-                        Session2TokensListenerRecord listenerRecord =
-                                mSession2TokensListenerRecords.remove(index);
-                        try {
-                            listenerRecord.listener.asBinder().unlinkToDeath(listenerRecord, 0);
-                        } catch (Exception e) {
-                            // Ignore exception.
-                        }
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        /**
-         * Handles the dispatching of the media button events to one of the
-         * registered listeners, or if there was none, broadcast an
-         * ACTION_MEDIA_BUTTON intent to the rest of the system.
-         *
-         * @param packageName The caller package
-         * @param asSystemService {@code true} if the event sent to the session as if it was come
-         *          from the system service instead of the app process. This helps sessions to
-         *          distinguish between the key injection by the app and key events from the
-         *          hardware devices. Should be used only when the volume key events aren't handled
-         *          by foreground activity. {@code false} otherwise to tell session about the real
-         *          caller.
-         * @param keyEvent a non-null KeyEvent whose key code is one of the
-         *            supported media buttons
-         * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
-         *            while this key event is dispatched.
-         */
-        @Override
-        public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
-                KeyEvent keyEvent, boolean needWakeLock) {
-            if (keyEvent == null || !KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
-                Log.w(TAG, "Attempted to dispatch null or non-media key event.");
-                return;
-            }
-
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                if (DEBUG) {
-                    Log.d(TAG, "dispatchMediaKeyEvent, pkg=" + packageName + " pid=" + pid
-                            + ", uid=" + uid + ", asSystem=" + asSystemService + ", event="
-                            + keyEvent);
-                }
-                if (!isUserSetupComplete()) {
-                    // Global media key handling can have the side-effect of starting new
-                    // activities which is undesirable while setup is in progress.
-                    Slog.i(TAG, "Not dispatching media key event because user "
-                            + "setup is in progress.");
-                    return;
-                }
-
-                synchronized (mLock) {
-                    boolean isGlobalPriorityActive = isGlobalPriorityActiveLocked();
-                    if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
-                        // Prevent dispatching key event through reflection while the global
-                        // priority session is active.
-                        Slog.i(TAG, "Only the system can dispatch media key event "
-                                + "to the global priority session.");
-                        return;
-                    }
-                    if (!isGlobalPriorityActive) {
-                        if (mCurrentFullUserRecord.mOnMediaKeyListener != null) {
-                            if (DEBUG_KEY_EVENT) {
-                                Log.d(TAG, "Send " + keyEvent + " to the media key listener");
-                            }
-                            try {
-                                mCurrentFullUserRecord.mOnMediaKeyListener.onMediaKey(keyEvent,
-                                        new MediaKeyListenerResultReceiver(packageName, pid, uid,
-                                                asSystemService, keyEvent, needWakeLock));
-                                return;
-                            } catch (RemoteException e) {
-                                Log.w(TAG, "Failed to send " + keyEvent
-                                        + " to the media key listener");
-                            }
-                        }
-                    }
-                    if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
-                        handleVoiceKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
-                                needWakeLock);
-                    } else {
-                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
-                                keyEvent, needWakeLock);
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void setCallback(ICallback callback) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
-                    throw new SecurityException("Only Bluetooth service processes can set"
-                            + " Callback");
-                }
-                synchronized (mLock) {
-                    int userId = UserHandle.getUserId(uid);
-                    FullUserRecord user = getFullUserRecordLocked(userId);
-                    if (user == null || user.mFullUserId != userId) {
-                        Log.w(TAG, "Only the full user can set the callback"
-                                + ", userId=" + userId);
-                        return;
-                    }
-                    user.mCallback = callback;
-                    Log.d(TAG, "The callback " + user.mCallback
-                            + " is set by " + getCallingPackageName(uid));
-                    if (user.mCallback == null) {
-                        return;
-                    }
-                    try {
-                        user.mCallback.asBinder().linkToDeath(
-                                new IBinder.DeathRecipient() {
-                                    @Override
-                                    public void binderDied() {
-                                        synchronized (mLock) {
-                                            user.mCallback = null;
-                                        }
-                                    }
-                                }, 0);
-                        user.pushAddressedPlayerChangedLocked();
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to set callback", e);
-                        user.mCallback = null;
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void setOnVolumeKeyLongPressListener(IOnVolumeKeyLongPressListener listener) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // Enforce SET_VOLUME_KEY_LONG_PRESS_LISTENER permission.
-                if (getContext().checkPermission(
-                        android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER, pid, uid)
-                            != PackageManager.PERMISSION_GRANTED) {
-                    throw new SecurityException("Must hold the SET_VOLUME_KEY_LONG_PRESS_LISTENER" +
-                            " permission.");
-                }
-
-                synchronized (mLock) {
-                    int userId = UserHandle.getUserId(uid);
-                    FullUserRecord user = getFullUserRecordLocked(userId);
-                    if (user == null || user.mFullUserId != userId) {
-                        Log.w(TAG, "Only the full user can set the volume key long-press listener"
-                                + ", userId=" + userId);
-                        return;
-                    }
-                    if (user.mOnVolumeKeyLongPressListener != null &&
-                            user.mOnVolumeKeyLongPressListenerUid != uid) {
-                        Log.w(TAG, "The volume key long-press listener cannot be reset"
-                                + " by another app , mOnVolumeKeyLongPressListener="
-                                + user.mOnVolumeKeyLongPressListenerUid
-                                + ", uid=" + uid);
-                        return;
-                    }
-
-                    user.mOnVolumeKeyLongPressListener = listener;
-                    user.mOnVolumeKeyLongPressListenerUid = uid;
-
-                    Log.d(TAG, "The volume key long-press listener "
-                            + listener + " is set by " + getCallingPackageName(uid));
-
-                    if (user.mOnVolumeKeyLongPressListener != null) {
-                        try {
-                            user.mOnVolumeKeyLongPressListener.asBinder().linkToDeath(
-                                    new IBinder.DeathRecipient() {
-                                        @Override
-                                        public void binderDied() {
-                                            synchronized (mLock) {
-                                                user.mOnVolumeKeyLongPressListener = null;
-                                            }
-                                        }
-                                    }, 0);
-                        } catch (RemoteException e) {
-                            Log.w(TAG, "Failed to set death recipient "
-                                    + user.mOnVolumeKeyLongPressListener);
-                            user.mOnVolumeKeyLongPressListener = null;
-                        }
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void setOnMediaKeyListener(IOnMediaKeyListener listener) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // Enforce SET_MEDIA_KEY_LISTENER permission.
-                if (getContext().checkPermission(
-                        android.Manifest.permission.SET_MEDIA_KEY_LISTENER, pid, uid)
-                            != PackageManager.PERMISSION_GRANTED) {
-                    throw new SecurityException("Must hold the SET_MEDIA_KEY_LISTENER" +
-                            " permission.");
-                }
-
-                synchronized (mLock) {
-                    int userId = UserHandle.getUserId(uid);
-                    FullUserRecord user = getFullUserRecordLocked(userId);
-                    if (user == null || user.mFullUserId != userId) {
-                        Log.w(TAG, "Only the full user can set the media key listener"
-                                + ", userId=" + userId);
-                        return;
-                    }
-                    if (user.mOnMediaKeyListener != null && user.mOnMediaKeyListenerUid != uid) {
-                        Log.w(TAG, "The media key listener cannot be reset by another app. "
-                                + ", mOnMediaKeyListenerUid=" + user.mOnMediaKeyListenerUid
-                                + ", uid=" + uid);
-                        return;
-                    }
-
-                    user.mOnMediaKeyListener = listener;
-                    user.mOnMediaKeyListenerUid = uid;
-
-                    Log.d(TAG, "The media key listener " + user.mOnMediaKeyListener
-                            + " is set by " + getCallingPackageName(uid));
-
-                    if (user.mOnMediaKeyListener != null) {
-                        try {
-                            user.mOnMediaKeyListener.asBinder().linkToDeath(
-                                    new IBinder.DeathRecipient() {
-                                        @Override
-                                        public void binderDied() {
-                                            synchronized (mLock) {
-                                                user.mOnMediaKeyListener = null;
-                                            }
-                                        }
-                                    }, 0);
-                        } catch (RemoteException e) {
-                            Log.w(TAG, "Failed to set death recipient " + user.mOnMediaKeyListener);
-                            user.mOnMediaKeyListener = null;
-                        }
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        /**
-         * Handles the dispatching of the volume button events to one of the
-         * registered listeners. If there's a volume key long-press listener and
-         * there's no active global priority session, long-pressess will be sent to the
-         * long-press listener instead of adjusting volume.
-         *
-         * @param packageName The caller's package name, obtained by Context#getPackageName()
-         * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
-         * @param asSystemService {@code true} if the event sent to the session as if it was come
-         *          from the system service instead of the app process. This helps sessions to
-         *          distinguish between the key injection by the app and key events from the
-         *          hardware devices. Should be used only when the volume key events aren't handled
-         *          by foreground activity. {@code false} otherwise to tell session about the real
-         *          caller.
-         * @param keyEvent a non-null KeyEvent whose key code is one of the
-         *            {@link KeyEvent#KEYCODE_VOLUME_UP},
-         *            {@link KeyEvent#KEYCODE_VOLUME_DOWN},
-         *            or {@link KeyEvent#KEYCODE_VOLUME_MUTE}.
-         * @param stream stream type to adjust volume.
-         * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
-         */
-        @Override
-        public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
-                boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
-            if (keyEvent == null ||
-                    (keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
-                             && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
-                             && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_MUTE)) {
-                Log.w(TAG, "Attempted to dispatch null or non-volume key event.");
-                return;
-            }
-
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-
-            if (DEBUG_KEY_EVENT) {
-                Log.d(TAG, "dispatchVolumeKeyEvent, pkg=" + packageName + ", pid=" + pid + ", uid="
-                        + uid + ", asSystem=" + asSystemService + ", event=" + keyEvent);
-            }
-
-            try {
-                synchronized (mLock) {
-                    if (isGlobalPriorityActiveLocked()
-                            || mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
-                        dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
-                                asSystemService, keyEvent, stream, musicOnly);
-                    } else {
-                        // TODO: Consider the case when both volume up and down keys are pressed
-                        //       at the same time.
-                        if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
-                            if (keyEvent.getRepeatCount() == 0) {
-                                // Keeps the copy of the KeyEvent because it can be reused.
-                                mCurrentFullUserRecord.mInitialDownVolumeKeyEvent =
-                                        KeyEvent.obtain(keyEvent);
-                                mCurrentFullUserRecord.mInitialDownVolumeStream = stream;
-                                mCurrentFullUserRecord.mInitialDownMusicOnly = musicOnly;
-                                mHandler.sendMessageDelayed(
-                                        mHandler.obtainMessage(
-                                                MessageHandler.MSG_VOLUME_INITIAL_DOWN,
-                                                mCurrentFullUserRecord.mFullUserId, 0),
-                                        mLongPressTimeout);
-                            }
-                            if (keyEvent.getRepeatCount() > 0 || keyEvent.isLongPress()) {
-                                mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
-                                if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null) {
-                                    dispatchVolumeKeyLongPressLocked(
-                                            mCurrentFullUserRecord.mInitialDownVolumeKeyEvent);
-                                    // Mark that the key is already handled.
-                                    mCurrentFullUserRecord.mInitialDownVolumeKeyEvent = null;
-                                }
-                                dispatchVolumeKeyLongPressLocked(keyEvent);
-                            }
-                        } else { // if up
-                            mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
-                            if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null
-                                    && mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
-                                            .getDownTime() == keyEvent.getDownTime()) {
-                                // Short-press. Should change volume.
-                                dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
-                                        asSystemService,
-                                        mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
-                                        mCurrentFullUserRecord.mInitialDownVolumeStream,
-                                        mCurrentFullUserRecord.mInitialDownMusicOnly);
-                                dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
-                                        asSystemService, keyEvent, stream, musicOnly);
-                            } else {
-                                dispatchVolumeKeyLongPressLocked(keyEvent);
-                            }
-                        }
-                    }
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid,
-                int uid, boolean asSystemService, KeyEvent keyEvent, int stream,
-                boolean musicOnly) {
-            boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
-            boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
-            int direction = 0;
-            boolean isMute = false;
-            switch (keyEvent.getKeyCode()) {
-                case KeyEvent.KEYCODE_VOLUME_UP:
-                    direction = AudioManager.ADJUST_RAISE;
-                    break;
-                case KeyEvent.KEYCODE_VOLUME_DOWN:
-                    direction = AudioManager.ADJUST_LOWER;
-                    break;
-                case KeyEvent.KEYCODE_VOLUME_MUTE:
-                    isMute = true;
-                    break;
-            }
-            if (down || up) {
-                int flags = AudioManager.FLAG_FROM_KEY;
-                if (musicOnly) {
-                    // This flag is used when the screen is off to only affect active media.
-                    flags |= AudioManager.FLAG_ACTIVE_MEDIA_ONLY;
-                } else {
-                    // These flags are consistent with the home screen
-                    if (up) {
-                        flags |= AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
-                    } else {
-                        flags |= AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
-                    }
-                }
-                if (direction != 0) {
-                    // If this is action up we want to send a beep for non-music events
-                    if (up) {
-                        direction = 0;
-                    }
-                    dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
-                            asSystemService, stream, direction, flags);
-                } else if (isMute) {
-                    if (down && keyEvent.getRepeatCount() == 0) {
-                        dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
-                                asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void dispatchAdjustVolume(String packageName, String opPackageName,
-                int suggestedStream, int delta, int flags) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                synchronized (mLock) {
-                    dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false,
-                            suggestedStream, delta, flags);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public void setRemoteVolumeController(IRemoteVolumeController rvc) {
-            final int pid = Binder.getCallingPid();
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                enforceSystemUiPermission("listen for volume changes", pid, uid);
-                mRvc = rvc;
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
-        public boolean isGlobalPriorityActive() {
-            synchronized (mLock) {
-                return isGlobalPriorityActiveLocked();
-            }
-        }
-
-        @Override
-        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
-            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
-
-            pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
-            pw.println();
-
-            synchronized (mLock) {
-                pw.println(mSessionsListeners.size() + " sessions listeners.");
-                pw.println("Global priority session is " + mGlobalPrioritySession);
-                if (mGlobalPrioritySession != null) {
-                    mGlobalPrioritySession.dump(pw, "  ");
-                }
-                pw.println("User Records:");
-                int count = mUserRecords.size();
-                for (int i = 0; i < count; i++) {
-                    mUserRecords.valueAt(i).dumpLocked(pw, "");
-                }
-                mAudioPlayerStateMonitor.dump(getContext(), pw, "");
-            }
-        }
-
-        /**
-         * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
-         * permission or an enabled notification listener)
-         *
-         * @param controllerPackageName package name of the controller app
-         * @param controllerPid pid of the controller app
-         * @param controllerUid uid of the controller app
-         */
-        @Override
-        public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
-                throws RemoteException {
-            final int uid = Binder.getCallingUid();
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // Don't perform sanity check between controllerPackageName and controllerUid.
-                // When an (activity|service) runs on the another apps process by specifying
-                // android:process in the AndroidManifest.xml, then PID and UID would have the
-                // running process' information instead of the (activity|service) that has created
-                // MediaController.
-                // Note that we can use Context#getOpPackageName() instead of
-                // Context#getPackageName() for getting package name that matches with the PID/UID,
-                // but it doesn't tell which package has created the MediaController, so useless.
-                return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
-                        controllerPid, controllerUid);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        // For MediaSession
-        private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
-                final int uid) {
-            String packageName = null;
-            if (componentName != null) {
-                // If they gave us a component name verify they own the
-                // package
-                packageName = componentName.getPackageName();
-                enforcePackageName(packageName, uid);
-            }
-            // Check that they can make calls on behalf of the user and
-            // get the final user id
-            int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
-                    true /* allowAll */, true /* requireFull */, "getSessions", packageName);
-            // Check if they have the permissions or their component is
-            // enabled for the user they're calling from.
-            enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
-            return resolvedUserId;
-        }
-
-        private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
-                int pid, int uid) throws RemoteException {
-            // Allow API calls from the System UI
-            if (isCurrentVolumeController(pid, uid)) {
-                return true;
-            }
-
-            // Check if it's system server or has MEDIA_CONTENT_CONTROL.
-            // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
-            // check here.
-            if (uid == Process.SYSTEM_UID || getContext().checkPermission(
-                    android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
-                    == PackageManager.PERMISSION_GRANTED) {
-                return true;
-            } else if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
-            }
-
-            // You may not access another user's content as an enabled listener.
-            final int userId = UserHandle.getUserId(uid);
-            if (resolvedUserId != userId) {
-                return false;
-            }
-
-            // TODO(jaewan): (Post-P) Propose NotificationManager#hasEnabledNotificationListener(
-            //               String pkgName) to notification team for optimization
-            final List<ComponentName> enabledNotificationListeners =
-                    mNotificationManager.getEnabledNotificationListeners(userId);
-            if (enabledNotificationListeners != null) {
-                for (int i = 0; i < enabledNotificationListeners.size(); i++) {
-                    if (TextUtils.equals(packageName,
-                            enabledNotificationListeners.get(i).getPackageName())) {
-                        return true;
-                    }
-                }
-            }
-            if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
-                        + "notification listener");
-            }
-            return false;
-        }
-
-        private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
-                int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
-            MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
-                    : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
-
-            boolean preferSuggestedStream = false;
-            if (isValidLocalStreamType(suggestedStream)
-                    && AudioSystem.isStreamActive(suggestedStream, 0)) {
-                preferSuggestedStream = true;
-            }
-            if (DEBUG_KEY_EVENT) {
-                Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
-                        + flags + ", suggestedStream=" + suggestedStream
-                        + ", preferSuggestedStream=" + preferSuggestedStream);
-            }
-            if (session == null || preferSuggestedStream) {
-                if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
-                        && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
-                    if (DEBUG) {
-                        Log.d(TAG, "No active session to adjust, skipping media only volume event");
-                    }
-                    return;
-                }
-
-                // Execute mAudioService.adjustSuggestedStreamVolume() on
-                // handler thread of MediaSessionService.
-                // This will release the MediaSessionService.mLock sooner and avoid
-                // a potential deadlock between MediaSessionService.mLock and
-                // ActivityManagerService lock.
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        final String callingOpPackageName;
-                        final int callingUid;
-                        if (asSystemService) {
-                            callingOpPackageName = getContext().getOpPackageName();
-                            callingUid = Process.myUid();
-                        } else {
-                            callingOpPackageName = opPackageName;
-                            callingUid = uid;
-                        }
-                        try {
-                            mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
-                                    direction, flags, callingOpPackageName, callingUid);
-                        } catch (SecurityException | IllegalArgumentException e) {
-                            Log.e(TAG, "Cannot adjust volume: direction=" + direction
-                                    + ", suggestedStream=" + suggestedStream + ", flags=" + flags
-                                    + ", packageName=" + packageName + ", uid=" + uid
-                                    + ", asSystemService=" + asSystemService, e);
-                        }
-                    }
-                });
-            } else {
-                session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
-                        direction, flags, true);
-            }
-        }
-
-        private void handleVoiceKeyEventLocked(String packageName, int pid, int uid,
-                boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
-            int action = keyEvent.getAction();
-            boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
-            if (action == KeyEvent.ACTION_DOWN) {
-                if (keyEvent.getRepeatCount() == 0) {
-                    mVoiceButtonDown = true;
-                    mVoiceButtonHandled = false;
-                } else if (mVoiceButtonDown && !mVoiceButtonHandled && isLongPress) {
-                    mVoiceButtonHandled = true;
-                    startVoiceInput(needWakeLock);
-                }
-            } else if (action == KeyEvent.ACTION_UP) {
-                if (mVoiceButtonDown) {
-                    mVoiceButtonDown = false;
-                    if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
-                        // Resend the down then send this event through
-                        KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
-                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
-                                downEvent, needWakeLock);
-                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
-                                keyEvent, needWakeLock);
-                    }
-                }
-            }
-        }
-
-        private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
-                boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
-            MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
-            if (session != null) {
-                if (DEBUG_KEY_EVENT) {
-                    Log.d(TAG, "Sending " + keyEvent + " to " + session);
-                }
-                if (needWakeLock) {
-                    mKeyEventReceiver.aquireWakeLockLocked();
-                }
-                // If we don't need a wakelock use -1 as the id so we won't release it later.
-                session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
-                        needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
-                        mKeyEventReceiver);
-                if (mCurrentFullUserRecord.mCallback != null) {
-                    try {
-                        mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
-                                keyEvent, new MediaSession.Token(session.getControllerBinder()));
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to send callback", e);
-                    }
-                }
-            } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
-                    || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
-                if (needWakeLock) {
-                    mKeyEventReceiver.aquireWakeLockLocked();
-                }
-                Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
-                mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
-                // TODO: Find a way to also send PID/UID in secure way.
-                String callerPackageName =
-                        (asSystemService) ? getContext().getPackageName() : packageName;
-                mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callerPackageName);
-                try {
-                    if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
-                        PendingIntent receiver = mCurrentFullUserRecord.mLastMediaButtonReceiver;
-                        if (DEBUG_KEY_EVENT) {
-                            Log.d(TAG, "Sending " + keyEvent
-                                    + " to the last known PendingIntent " + receiver);
-                        }
-                        receiver.send(getContext(),
-                                needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
-                                mediaButtonIntent, mKeyEventReceiver, mHandler);
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            ComponentName componentName = mCurrentFullUserRecord
-                                    .mLastMediaButtonReceiver.getIntent().getComponent();
-                            if (componentName != null) {
-                                mCurrentFullUserRecord.mCallback
-                                        .onMediaKeyEventDispatchedToMediaButtonReceiver(
-                                                keyEvent, componentName);
-                            }
-                        }
-                    } else {
-                        ComponentName receiver =
-                                mCurrentFullUserRecord.mRestoredMediaButtonReceiver;
-                        int componentType = mCurrentFullUserRecord
-                                .mRestoredMediaButtonReceiverComponentType;
-                        UserHandle userHandle = UserHandle.of(mCurrentFullUserRecord
-                                .mRestoredMediaButtonReceiverUserId);
-                        if (DEBUG_KEY_EVENT) {
-                            Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
-                                    + receiver + ", type=" + componentType);
-                        }
-                        mediaButtonIntent.setComponent(receiver);
-                        try {
-                            switch (componentType) {
-                                case FullUserRecord.COMPONENT_TYPE_ACTIVITY:
-                                    getContext().startActivityAsUser(mediaButtonIntent, userHandle);
-                                    break;
-                                case FullUserRecord.COMPONENT_TYPE_SERVICE:
-                                    getContext().startForegroundServiceAsUser(mediaButtonIntent,
-                                            userHandle);
-                                    break;
-                                default:
-                                    // Legacy behavior for other cases.
-                                    getContext().sendBroadcastAsUser(mediaButtonIntent, userHandle);
-                            }
-                        } catch (Exception e) {
-                            Log.w(TAG, "Error sending media button to the restored intent "
-                                    + receiver + ", type=" + componentType, e);
-                        }
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            mCurrentFullUserRecord.mCallback
-                                    .onMediaKeyEventDispatchedToMediaButtonReceiver(
-                                            keyEvent, receiver);
-                        }
-                    }
-                } catch (CanceledException e) {
-                    Log.i(TAG, "Error sending key event to media button receiver "
-                            + mCurrentFullUserRecord.mLastMediaButtonReceiver, e);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to send callback", e);
-                }
-            }
-        }
-
-        private void startVoiceInput(boolean needWakeLock) {
-            Intent voiceIntent = null;
-            // select which type of search to launch:
-            // - screen on and device unlocked: action is ACTION_WEB_SEARCH
-            // - device locked or screen off: action is
-            // ACTION_VOICE_SEARCH_HANDS_FREE
-            // with EXTRA_SECURE set to true if the device is securely locked
-            PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
-            boolean isLocked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
-            if (!isLocked && pm.isScreenOn()) {
-                voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
-                Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
-            } else {
-                voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
-                voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
-                        isLocked && mKeyguardManager.isKeyguardSecure());
-                Log.i(TAG, "voice-based interactions: about to use ACTION_VOICE_SEARCH_HANDS_FREE");
-            }
-            // start the search activity
-            if (needWakeLock) {
-                mMediaEventWakeLock.acquire();
-            }
-            try {
-                if (voiceIntent != null) {
-                    voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-                    if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
-                    getContext().startActivityAsUser(voiceIntent, UserHandle.CURRENT);
-                }
-            } catch (ActivityNotFoundException e) {
-                Log.w(TAG, "No activity for search: " + e);
-            } finally {
-                if (needWakeLock) {
-                    mMediaEventWakeLock.release();
-                }
-            }
-        }
-
-        private boolean isVoiceKey(int keyCode) {
-            return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
-                    || (!mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
-        }
-
-        private boolean isUserSetupComplete() {
-            return Settings.Secure.getIntForUser(getContext().getContentResolver(),
-                    Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
-        }
-
-        // we only handle public stream types, which are 0-5
-        private boolean isValidLocalStreamType(int streamType) {
-            return streamType >= AudioManager.STREAM_VOICE_CALL
-                    && streamType <= AudioManager.STREAM_NOTIFICATION;
-        }
-
-        private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
-            private final String mPackageName;
-            private final int mPid;
-            private final int mUid;
-            private final boolean mAsSystemService;
-            private final KeyEvent mKeyEvent;
-            private final boolean mNeedWakeLock;
-            private boolean mHandled;
-
-            private MediaKeyListenerResultReceiver(String packageName, int pid, int uid,
-                    boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
-                super(mHandler);
-                mHandler.postDelayed(this, MEDIA_KEY_LISTENER_TIMEOUT);
-                mPackageName = packageName;
-                mPid = pid;
-                mUid = uid;
-                mAsSystemService = asSystemService;
-                mKeyEvent = keyEvent;
-                mNeedWakeLock = needWakeLock;
-            }
-
-            @Override
-            public void run() {
-                Log.d(TAG, "The media key listener is timed-out for " + mKeyEvent);
-                dispatchMediaKeyEvent();
-            }
-
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode == MediaSessionManager.RESULT_MEDIA_KEY_HANDLED) {
-                    mHandled = true;
-                    mHandler.removeCallbacks(this);
-                    return;
-                }
-                dispatchMediaKeyEvent();
-            }
-
-            private void dispatchMediaKeyEvent() {
-                if (mHandled) {
-                    return;
-                }
-                mHandled = true;
-                mHandler.removeCallbacks(this);
-                synchronized (mLock) {
-                    if (!isGlobalPriorityActiveLocked()
-                            && isVoiceKey(mKeyEvent.getKeyCode())) {
-                        handleVoiceKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
-                                mKeyEvent, mNeedWakeLock);
-                    } else {
-                        dispatchMediaKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
-                                mKeyEvent, mNeedWakeLock);
-                    }
-                }
-            }
-        }
-
-        private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler);
-
-        class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable,
-                PendingIntent.OnFinished {
-            private final Handler mHandler;
-            private int mRefCount = 0;
-            private int mLastTimeoutId = 0;
-
-            public KeyEventWakeLockReceiver(Handler handler) {
-                super(handler);
-                mHandler = handler;
-            }
-
-            public void onTimeout() {
-                synchronized (mLock) {
-                    if (mRefCount == 0) {
-                        // We've already released it, so just return
-                        return;
-                    }
-                    mLastTimeoutId++;
-                    mRefCount = 0;
-                    releaseWakeLockLocked();
-                }
-            }
-
-            public void aquireWakeLockLocked() {
-                if (mRefCount == 0) {
-                    mMediaEventWakeLock.acquire();
-                }
-                mRefCount++;
-                mHandler.removeCallbacks(this);
-                mHandler.postDelayed(this, WAKELOCK_TIMEOUT);
-
-            }
-
-            @Override
-            public void run() {
-                onTimeout();
-            }
-
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode < mLastTimeoutId) {
-                    // Ignore results from calls that were before the last
-                    // timeout, just in case.
-                    return;
-                } else {
-                    synchronized (mLock) {
-                        if (mRefCount > 0) {
-                            mRefCount--;
-                            if (mRefCount == 0) {
-                                releaseWakeLockLocked();
-                            }
-                        }
-                    }
-                }
-            }
-
-            private void releaseWakeLockLocked() {
-                mMediaEventWakeLock.release();
-                mHandler.removeCallbacks(this);
-            }
-
-            @Override
-            public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
-                    String resultData, Bundle resultExtras) {
-                onReceiveResult(resultCode, null);
-            }
-        };
-
-        BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (intent == null) {
-                    return;
-                }
-                Bundle extras = intent.getExtras();
-                if (extras == null) {
-                    return;
-                }
-                synchronized (mLock) {
-                    if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
-                            && mMediaEventWakeLock.isHeld()) {
-                        mMediaEventWakeLock.release();
-                    }
-                }
-            }
-        };
-    }
-
-    final class MessageHandler extends Handler {
-        private static final int MSG_SESSIONS_CHANGED = 1;
-        private static final int MSG_VOLUME_INITIAL_DOWN = 2;
-        private final SparseArray<Integer> mIntegerCache = new SparseArray<>();
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_SESSIONS_CHANGED:
-                    pushSessionsChanged((int) msg.obj);
-                    break;
-                case MSG_VOLUME_INITIAL_DOWN:
-                    synchronized (mLock) {
-                        FullUserRecord user = mUserRecords.get((int) msg.arg1);
-                        if (user != null && user.mInitialDownVolumeKeyEvent != null) {
-                            dispatchVolumeKeyLongPressLocked(user.mInitialDownVolumeKeyEvent);
-                            // Mark that the key is already handled.
-                            user.mInitialDownVolumeKeyEvent = null;
-                        }
-                    }
-                    break;
-            }
-        }
-
-        public void postSessionsChanged(int userId) {
-            // Use object instead of the arguments when posting message to remove pending requests.
-            Integer userIdInteger = mIntegerCache.get(userId);
-            if (userIdInteger == null) {
-                userIdInteger = Integer.valueOf(userId);
-                mIntegerCache.put(userId, userIdInteger);
-            }
-            removeMessages(MSG_SESSIONS_CHANGED, userIdInteger);
-            obtainMessage(MSG_SESSIONS_CHANGED, userIdInteger).sendToTarget();
-        }
-    }
-
-    private class Controller2Callback extends MediaController2.ControllerCallback {
-        private final Session2Token mToken;
-
-        Controller2Callback(Session2Token token) {
-            mToken = token;
-        }
-
-        @Override
-        public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
-            synchronized (mLock) {
-                int userId = UserHandle.getUserId(mToken.getUid());
-                mSession2TokensPerUser.get(userId).add(mToken);
-                pushSession2TokensChangedLocked(userId);
-            }
-        }
-
-        @Override
-        public void onDisconnected(MediaController2 controller) {
-            synchronized (mLock) {
-                int userId = UserHandle.getUserId(mToken.getUid());
-                mSession2TokensPerUser.get(userId).remove(mToken);
-                pushSession2TokensChangedLocked(userId);
-            }
-        }
+    abstract static class ServiceImpl {
+        public abstract void onStart();
+        public abstract void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session);
+        public abstract void onSessionPlaystateChanged(
+                MediaSessionRecord record, int oldState, int newState);
+        public abstract void onSessionPlaybackTypeChanged(MediaSessionRecord record);
+        public abstract void onStartUser(int userId);
+        public abstract void onSwitchUser(int userId);
+        public abstract void monitor();
+        public abstract void onMediaButtonReceiverChanged(MediaSessionRecord record);
+        protected abstract void enforcePhoneStatePermission(int pid, int uid);
+        abstract void updateSession(MediaSessionRecord record);
+        abstract void setGlobalPrioritySession(MediaSessionRecord record);
+        abstract List<Session2Token> getSession2TokensLocked(int userId);
+        abstract void onStopUser(int userId);
+        abstract void sessionDied(MediaSessionRecord session);
+        abstract void destroySession(MediaSessionRecord session);
+        abstract void pushSession2TokensChangedLocked(int userId);
+        abstract Context getContext();
+        abstract IBinder getServiceBinder();
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
new file mode 100644
index 0000000..f374c6d
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -0,0 +1,2142 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static android.os.UserHandle.USER_ALL;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.media.AudioManagerInternal;
+import android.media.AudioPlaybackConfiguration;
+import android.media.AudioSystem;
+import android.media.IAudioService;
+import android.media.IRemoteVolumeController;
+import android.media.MediaController2;
+import android.media.Session2CommandGroup;
+import android.media.Session2Token;
+import android.media.session.IActiveSessionsListener;
+import android.media.session.ICallback;
+import android.media.session.IOnMediaKeyListener;
+import android.media.session.IOnVolumeKeyLongPressListener;
+import android.media.session.ISession;
+import android.media.session.ISession2TokensListener;
+import android.media.session.ISessionManager;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.media.session.SessionCallbackLink;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.speech.RecognizerIntent;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.view.KeyEvent;
+import android.view.ViewConfiguration;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * System implementation of MediaSessionManager
+ */
+public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
+    private static final String TAG = "MediaSessionService";
+    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    // Leave log for key event always.
+    private static final boolean DEBUG_KEY_EVENT = true;
+
+    private static final int WAKELOCK_TIMEOUT = 5000;
+    private static final int MEDIA_KEY_LISTENER_TIMEOUT = 1000;
+
+    private final Context mContext;
+    private final SessionManagerImpl mSessionManagerImpl;
+    private final MessageHandler mHandler = new MessageHandler();
+    private final PowerManager.WakeLock mMediaEventWakeLock;
+    private final int mLongPressTimeout;
+    private final INotificationManager mNotificationManager;
+    private final Object mLock = new Object();
+    // Keeps the full user id for each user.
+    @GuardedBy("mLock")
+    private final SparseIntArray mFullUserIds = new SparseIntArray();
+    @GuardedBy("mLock")
+    private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<FullUserRecord>();
+    @GuardedBy("mLock")
+    private final ArrayList<SessionsListenerRecord> mSessionsListeners =
+            new ArrayList<SessionsListenerRecord>();
+    // Map user id as index to list of Session2Tokens
+    // TODO: Keep session2 info in MediaSessionStack for prioritizing both session1 and session2 in
+    //       one place.
+    @GuardedBy("mLock")
+    private final SparseArray<List<Session2Token>> mSession2TokensPerUser = new SparseArray<>();
+    @GuardedBy("mLock")
+    private final List<Session2TokensListenerRecord> mSession2TokensListenerRecords =
+            new ArrayList<>();
+
+    private KeyguardManager mKeyguardManager;
+    private IAudioService mAudioService;
+    private AudioManagerInternal mAudioManagerInternal;
+    private ActivityManager mActivityManager;
+    private ContentResolver mContentResolver;
+    private SettingsObserver mSettingsObserver;
+    private boolean mHasFeatureLeanback;
+
+    // The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
+    // It's always not null after the MediaSessionService is started.
+    private FullUserRecord mCurrentFullUserRecord;
+    private MediaSessionRecord mGlobalPrioritySession;
+    private AudioPlayerStateMonitor mAudioPlayerStateMonitor;
+
+    // Used to notify system UI when remote volume was changed. TODO find a
+    // better way to handle this.
+    private IRemoteVolumeController mRvc;
+
+    public MediaSessionServiceImpl(Context context) {
+        mContext = context;
+        mSessionManagerImpl = new SessionManagerImpl();
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
+        mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
+        mNotificationManager = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+    }
+
+    Context getContext() {
+        return mContext;
+    }
+
+    IBinder getServiceBinder() {
+        return mSessionManagerImpl;
+    }
+
+    @Override
+    public void onStart() {
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mAudioService = getAudioService();
+        mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
+        mActivityManager =
+                (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance();
+        mAudioPlayerStateMonitor.registerListener(
+                (config, isRemoved) -> {
+                    if (isRemoved || !config.isActive() || config.getPlayerType()
+                            == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
+                        return;
+                    }
+                    synchronized (mLock) {
+                        FullUserRecord user = getFullUserRecordLocked(
+                                UserHandle.getUserId(config.getClientUid()));
+                        if (user != null) {
+                            user.mPriorityStack.updateMediaButtonSessionIfNeeded();
+                        }
+                    }
+                }, null /* handler */);
+        mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);
+        mContentResolver = mContext.getContentResolver();
+        mSettingsObserver = new SettingsObserver();
+        mSettingsObserver.observe();
+        mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK);
+
+        updateUser();
+    }
+
+    private IAudioService getAudioService() {
+        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+        return IAudioService.Stub.asInterface(b);
+    }
+
+    private boolean isGlobalPriorityActiveLocked() {
+        return mGlobalPrioritySession != null && mGlobalPrioritySession.isActive();
+    }
+
+    @Override
+    public void updateSession(MediaSessionRecord record) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+            if (user == null) {
+                Log.w(TAG, "Unknown session updated. Ignoring.");
+                return;
+            }
+            if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+                if (DEBUG_KEY_EVENT) {
+                    Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
+                }
+                user.pushAddressedPlayerChangedLocked();
+            } else {
+                if (!user.mPriorityStack.contains(record)) {
+                    Log.w(TAG, "Unknown session updated. Ignoring.");
+                    return;
+                }
+                user.mPriorityStack.onSessionStateChange(record);
+            }
+            mHandler.postSessionsChanged(record.getUserId());
+        }
+    }
+
+    @Override
+    public void setGlobalPrioritySession(MediaSessionRecord record) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+            if (mGlobalPrioritySession != record) {
+                Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+                        + " to " + record);
+                mGlobalPrioritySession = record;
+                if (user != null && user.mPriorityStack.contains(record)) {
+                    // Handle the global priority session separately.
+                    // Otherwise, it can be the media button session regardless of the active state
+                    // because it or other system components might have been the lastly played media
+                    // app.
+                    user.mPriorityStack.removeSession(record);
+                }
+            }
+        }
+    }
+
+    private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
+        List<MediaSessionRecord> records = new ArrayList<>();
+        if (userId == USER_ALL) {
+            int size = mUserRecords.size();
+            for (int i = 0; i < size; i++) {
+                records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
+            }
+        } else {
+            FullUserRecord user = getFullUserRecordLocked(userId);
+            if (user == null) {
+                Log.w(TAG, "getSessions failed. Unknown user " + userId);
+                return records;
+            }
+            records.addAll(user.mPriorityStack.getActiveSessions(userId));
+        }
+
+        // Return global priority session at the first whenever it's asked.
+        if (isGlobalPriorityActiveLocked()
+                && (userId == USER_ALL || userId == mGlobalPrioritySession.getUserId())) {
+            records.add(0, mGlobalPrioritySession);
+        }
+        return records;
+    }
+
+    List<Session2Token> getSession2TokensLocked(int userId) {
+        List<Session2Token> list = new ArrayList<>();
+        if (userId == USER_ALL) {
+            for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
+                list.addAll(mSession2TokensPerUser.valueAt(i));
+            }
+        } else {
+            list.addAll(mSession2TokensPerUser.get(userId));
+        }
+        return list;
+    }
+
+    /**
+     * Tells the system UI that volume has changed on an active remote session.
+     */
+    public void notifyRemoteVolumeChanged(int flags, MediaSessionRecord session) {
+        if (mRvc == null || !session.isActive()) {
+            return;
+        }
+        try {
+            mRvc.remoteVolumeChanged(session.getControllerBinder(), flags);
+        } catch (Exception e) {
+            Log.wtf(TAG, "Error sending volume change to system UI.", e);
+        }
+    }
+
+    @Override
+    public void onSessionPlaystateChanged(MediaSessionRecord record, int oldState, int newState) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+            if (user == null || !user.mPriorityStack.contains(record)) {
+                Log.d(TAG, "Unknown session changed playback state. Ignoring.");
+                return;
+            }
+            user.mPriorityStack.onPlaystateChanged(record, oldState, newState);
+        }
+    }
+
+    @Override
+    public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+            if (user == null || !user.mPriorityStack.contains(record)) {
+                Log.d(TAG, "Unknown session changed playback type. Ignoring.");
+                return;
+            }
+            pushRemoteVolumeUpdateLocked(record.getUserId());
+        }
+    }
+
+    @Override
+    public void onStartUser(int userId) {
+        if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
+        updateUser();
+    }
+
+    @Override
+    public void onSwitchUser(int userId) {
+        if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
+        updateUser();
+    }
+
+    // Called when the user with the userId is removed.
+    @Override
+    public void onStopUser(int userId) {
+        if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
+        synchronized (mLock) {
+            // TODO: Also handle removing user in updateUser() because adding/switching user is
+            //       handled in updateUser().
+            FullUserRecord user = getFullUserRecordLocked(userId);
+            if (user != null) {
+                if (user.mFullUserId == userId) {
+                    user.destroySessionsForUserLocked(USER_ALL);
+                    mUserRecords.remove(userId);
+                } else {
+                    user.destroySessionsForUserLocked(userId);
+                }
+            }
+            mSession2TokensPerUser.remove(userId);
+            updateUser();
+        }
+    }
+
+    @Override
+    public void monitor() {
+        synchronized (mLock) {
+            // Check for deadlock
+        }
+    }
+
+    protected void enforcePhoneStatePermission(int pid, int uid) {
+        if (mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Must hold the MODIFY_PHONE_STATE permission.");
+        }
+    }
+
+    void sessionDied(MediaSessionRecord session) {
+        synchronized (mLock) {
+            destroySessionLocked(session);
+        }
+    }
+
+    void destroySession(MediaSessionRecord session) {
+        synchronized (mLock) {
+            destroySessionLocked(session);
+        }
+    }
+
+    private void updateUser() {
+        synchronized (mLock) {
+            UserManager manager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+            mFullUserIds.clear();
+            List<UserInfo> allUsers = manager.getUsers();
+            if (allUsers != null) {
+                for (UserInfo userInfo : allUsers) {
+                    if (userInfo.isManagedProfile()) {
+                        mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
+                    } else {
+                        mFullUserIds.put(userInfo.id, userInfo.id);
+                        if (mUserRecords.get(userInfo.id) == null) {
+                            mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
+                        }
+                    }
+                    if (mSession2TokensPerUser.get(userInfo.id) == null) {
+                        mSession2TokensPerUser.put(userInfo.id, new ArrayList<>());
+                    }
+                }
+            }
+            // Ensure that the current full user exists.
+            int currentFullUserId = ActivityManager.getCurrentUser();
+            mCurrentFullUserRecord = mUserRecords.get(currentFullUserId);
+            if (mCurrentFullUserRecord == null) {
+                Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
+                mCurrentFullUserRecord = new FullUserRecord(currentFullUserId);
+                mUserRecords.put(currentFullUserId, mCurrentFullUserRecord);
+                if (mSession2TokensPerUser.get(currentFullUserId) == null) {
+                    mSession2TokensPerUser.put(currentFullUserId, new ArrayList<>());
+                }
+            }
+            mFullUserIds.put(currentFullUserId, currentFullUserId);
+        }
+    }
+
+    private void updateActiveSessionListeners() {
+        synchronized (mLock) {
+            for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+                SessionsListenerRecord listener = mSessionsListeners.get(i);
+                try {
+                    enforceMediaPermissions(listener.componentName, listener.pid, listener.uid,
+                            listener.userId);
+                } catch (SecurityException e) {
+                    Log.i(TAG, "ActiveSessionsListener " + listener.componentName
+                            + " is no longer authorized. Disconnecting.");
+                    mSessionsListeners.remove(i);
+                    try {
+                        listener.listener
+                                .onActiveSessionsChanged(new ArrayList<MediaSession.Token>());
+                    } catch (Exception e1) {
+                        // ignore
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * When a session is removed several things need to happen.
+     * 1. We need to remove it from the relevant user.
+     * 2. We need to remove it from the priority stack.
+     * 3. We need to remove it from all sessions.
+     * 4. If this is the system priority session we need to clear it.
+     * 5. We need to unlink to death from the cb binder
+     * 6. We need to tell the session to do any final cleanup (onDestroy)
+     */
+    private void destroySessionLocked(MediaSessionRecord session) {
+        if (DEBUG) {
+            Log.d(TAG, "Destroying " + session);
+        }
+        FullUserRecord user = getFullUserRecordLocked(session.getUserId());
+        if (mGlobalPrioritySession == session) {
+            mGlobalPrioritySession = null;
+            if (session.isActive() && user != null) {
+                user.pushAddressedPlayerChangedLocked();
+            }
+        } else {
+            if (user != null) {
+                user.mPriorityStack.removeSession(session);
+            }
+        }
+
+        try {
+            session.getCallback().getBinder().unlinkToDeath(session, 0);
+        } catch (Exception e) {
+            // ignore exceptions while destroying a session.
+        }
+        session.onDestroy();
+        mHandler.postSessionsChanged(session.getUserId());
+    }
+
+    private void enforcePackageName(String packageName, int uid) {
+        if (TextUtils.isEmpty(packageName)) {
+            throw new IllegalArgumentException("packageName may not be empty");
+        }
+        String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+        final int packageCount = packages.length;
+        for (int i = 0; i < packageCount; i++) {
+            if (packageName.equals(packages[i])) {
+                return;
+            }
+        }
+        throw new IllegalArgumentException("packageName is not owned by the calling process");
+    }
+
+    /**
+     * Checks a caller's authorization to register an IRemoteControlDisplay.
+     * Authorization is granted if one of the following is true:
+     * <ul>
+     * <li>the caller has android.Manifest.permission.MEDIA_CONTENT_CONTROL
+     * permission</li>
+     * <li>the caller's listener is one of the enabled notification listeners
+     * for the caller's user</li>
+     * </ul>
+     */
+    private void enforceMediaPermissions(ComponentName compName, int pid, int uid,
+            int resolvedUserId) {
+        if (isCurrentVolumeController(pid, uid)) return;
+        if (mContext
+                .checkPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+                != PackageManager.PERMISSION_GRANTED
+                && !isEnabledNotificationListener(compName, UserHandle.getUserId(uid),
+                resolvedUserId)) {
+            throw new SecurityException("Missing permission to control media.");
+        }
+    }
+
+    private boolean isCurrentVolumeController(int pid, int uid) {
+        return mContext.checkPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+                pid, uid) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    private void enforceSystemUiPermission(String action, int pid, int uid) {
+        if (!isCurrentVolumeController(pid, uid)) {
+            throw new SecurityException("Only system ui may " + action);
+        }
+    }
+
+    /**
+     * This checks if the component is an enabled notification listener for the
+     * specified user. Enabled components may only operate on behalf of the user
+     * they're running as.
+     *
+     * @param compName The component that is enabled.
+     * @param userId The user id of the caller.
+     * @param forUserId The user id they're making the request on behalf of.
+     * @return True if the component is enabled, false otherwise
+     */
+    private boolean isEnabledNotificationListener(ComponentName compName, int userId,
+            int forUserId) {
+        if (userId != forUserId) {
+            // You may not access another user's content as an enabled listener.
+            return false;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "Checking if enabled notification listener " + compName);
+        }
+        if (compName != null) {
+            try {
+                return mNotificationManager.isNotificationListenerAccessGrantedForUser(
+                        compName, userId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Dead NotificationManager in isEnabledNotificationListener", e);
+            }
+        }
+        return false;
+    }
+
+    private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
+            String callerPackageName, SessionCallbackLink cb, String tag) throws RemoteException {
+        synchronized (mLock) {
+            return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb, tag);
+        }
+    }
+
+    /*
+     * When a session is created the following things need to happen.
+     * 1. Its callback binder needs a link to death
+     * 2. It needs to be added to all sessions.
+     * 3. It needs to be added to the priority stack.
+     * 4. It needs to be added to the relevant user record.
+     */
+    private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
+            String callerPackageName, SessionCallbackLink cb, String tag) {
+        FullUserRecord user = getFullUserRecordLocked(userId);
+        if (user == null) {
+            Log.wtf(TAG, "Request from invalid user: " +  userId);
+            throw new RuntimeException("Session request from invalid user.");
+        }
+
+        final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
+                callerPackageName, cb, tag, this, mHandler.getLooper());
+        try {
+            cb.getBinder().linkToDeath(session, 0);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Media Session owner died prematurely.", e);
+        }
+
+        user.mPriorityStack.addSession(session);
+        mHandler.postSessionsChanged(userId);
+
+        if (DEBUG) {
+            Log.d(TAG, "Created session for " + callerPackageName + " with tag " + tag);
+        }
+        return session;
+    }
+
+    private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
+        for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+            if (mSessionsListeners.get(i).listener.asBinder() == listener.asBinder()) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private int findIndexOfSession2TokensListenerLocked(ISession2TokensListener listener) {
+        for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
+            if (mSession2TokensListenerRecords.get(i).listener.asBinder() == listener.asBinder()) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+
+    private void pushSessionsChanged(int userId) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(userId);
+            if (user == null) {
+                Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
+                return;
+            }
+            List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
+            int size = records.size();
+            ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
+            for (int i = 0; i < size; i++) {
+                tokens.add(new MediaSession.Token(records.get(i).getControllerBinder()));
+            }
+            pushRemoteVolumeUpdateLocked(userId);
+            for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
+                SessionsListenerRecord record = mSessionsListeners.get(i);
+                if (record.userId == USER_ALL || record.userId == userId) {
+                    try {
+                        record.listener.onActiveSessionsChanged(tokens);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Dead ActiveSessionsListener in pushSessionsChanged, removing",
+                                e);
+                        mSessionsListeners.remove(i);
+                    }
+                }
+            }
+        }
+    }
+
+    private void pushRemoteVolumeUpdateLocked(int userId) {
+        if (mRvc != null) {
+            try {
+                FullUserRecord user = getFullUserRecordLocked(userId);
+                if (user == null) {
+                    Log.w(TAG, "pushRemoteVolumeUpdateLocked failed. No user with id=" + userId);
+                    return;
+                }
+                MediaSessionRecord record = user.mPriorityStack.getDefaultRemoteSession(userId);
+                mRvc.updateRemoteController(record == null ? null : record.getControllerBinder());
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Error sending default remote volume to sys ui.", e);
+            }
+        }
+    }
+
+    void pushSession2TokensChangedLocked(int userId) {
+        List<Session2Token> allSession2Tokens = getSession2TokensLocked(USER_ALL);
+        List<Session2Token> session2Tokens = getSession2TokensLocked(userId);
+
+        for (int i = mSession2TokensListenerRecords.size() - 1; i >= 0; i--) {
+            Session2TokensListenerRecord listenerRecord = mSession2TokensListenerRecords.get(i);
+            try {
+                if (listenerRecord.userId == USER_ALL) {
+                    listenerRecord.listener.onSession2TokensChanged(allSession2Tokens);
+                } else if (listenerRecord.userId == userId) {
+                    listenerRecord.listener.onSession2TokensChanged(session2Tokens);
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to notify Session2Token change. Removing listener.", e);
+                mSession2TokensListenerRecords.remove(i);
+            }
+        }
+    }
+
+    /**
+     * Called when the media button receiver for the {@code record} is changed.
+     *
+     * @param record the media session whose media button receiver is updated.
+     */
+    public void onMediaButtonReceiverChanged(MediaSessionRecord record) {
+        synchronized (mLock) {
+            FullUserRecord user = getFullUserRecordLocked(record.getUserId());
+            MediaSessionRecord mediaButtonSession =
+                    user.mPriorityStack.getMediaButtonSession();
+            if (record == mediaButtonSession) {
+                user.rememberMediaButtonReceiverLocked(mediaButtonSession);
+            }
+        }
+    }
+
+    private String getCallingPackageName(int uid) {
+        String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+        if (packages != null && packages.length > 0) {
+            return packages[0];
+        }
+        return "";
+    }
+
+    private void dispatchVolumeKeyLongPressLocked(KeyEvent keyEvent) {
+        if (mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
+            return;
+        }
+        try {
+            mCurrentFullUserRecord.mOnVolumeKeyLongPressListener.onVolumeKeyLongPress(keyEvent);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to send " + keyEvent + " to volume key long-press listener");
+        }
+    }
+
+    private FullUserRecord getFullUserRecordLocked(int userId) {
+        int fullUserId = mFullUserIds.get(userId, -1);
+        if (fullUserId < 0) {
+            return null;
+        }
+        return mUserRecords.get(fullUserId);
+    }
+
+    /**
+     * Information about a full user and its corresponding managed profiles.
+     *
+     * <p>Since the full user runs together with its managed profiles, a user wouldn't differentiate
+     * them when he/she presses a media/volume button. So keeping media sessions for them in one
+     * place makes more sense and increases the readability.</p>
+     * <p>The contents of this object is guarded by {@link #mLock}.
+     */
+    final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
+        public static final int COMPONENT_TYPE_INVALID = 0;
+        public static final int COMPONENT_TYPE_BROADCAST = 1;
+        public static final int COMPONENT_TYPE_ACTIVITY = 2;
+        public static final int COMPONENT_TYPE_SERVICE = 3;
+        private static final String COMPONENT_NAME_USER_ID_DELIM = ",";
+
+        private final int mFullUserId;
+        private final MediaSessionStack mPriorityStack;
+        private PendingIntent mLastMediaButtonReceiver;
+        private ComponentName mRestoredMediaButtonReceiver;
+        private int mRestoredMediaButtonReceiverComponentType;
+        private int mRestoredMediaButtonReceiverUserId;
+
+        private IOnVolumeKeyLongPressListener mOnVolumeKeyLongPressListener;
+        private int mOnVolumeKeyLongPressListenerUid;
+        private KeyEvent mInitialDownVolumeKeyEvent;
+        private int mInitialDownVolumeStream;
+        private boolean mInitialDownMusicOnly;
+
+        private IOnMediaKeyListener mOnMediaKeyListener;
+        private int mOnMediaKeyListenerUid;
+        private ICallback mCallback;
+
+        FullUserRecord(int fullUserId) {
+            mFullUserId = fullUserId;
+            mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
+            // Restore the remembered media button receiver before the boot.
+            String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
+                    Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
+            if (mediaButtonReceiverInfo == null) {
+                return;
+            }
+            String[] tokens = mediaButtonReceiverInfo.split(COMPONENT_NAME_USER_ID_DELIM);
+            if (tokens == null || (tokens.length != 2 && tokens.length != 3)) {
+                return;
+            }
+            mRestoredMediaButtonReceiver = ComponentName.unflattenFromString(tokens[0]);
+            mRestoredMediaButtonReceiverUserId = Integer.parseInt(tokens[1]);
+            if (tokens.length == 3) {
+                mRestoredMediaButtonReceiverComponentType = Integer.parseInt(tokens[2]);
+            } else {
+                mRestoredMediaButtonReceiverComponentType =
+                        getComponentType(mRestoredMediaButtonReceiver);
+            }
+        }
+
+        public void destroySessionsForUserLocked(int userId) {
+            List<MediaSessionRecord> sessions = mPriorityStack.getPriorityList(false, userId);
+            for (MediaSessionRecord session : sessions) {
+                MediaSessionServiceImpl.this.destroySessionLocked(session);
+            }
+        }
+
+        public void dumpLocked(PrintWriter pw, String prefix) {
+            pw.print(prefix + "Record for full_user=" + mFullUserId);
+            // Dump managed profile user ids associated with this user.
+            int size = mFullUserIds.size();
+            for (int i = 0; i < size; i++) {
+                if (mFullUserIds.keyAt(i) != mFullUserIds.valueAt(i)
+                        && mFullUserIds.valueAt(i) == mFullUserId) {
+                    pw.print(", profile_user=" + mFullUserIds.keyAt(i));
+                }
+            }
+            pw.println();
+            String indent = prefix + "  ";
+            pw.println(indent + "Volume key long-press listener: " + mOnVolumeKeyLongPressListener);
+            pw.println(indent + "Volume key long-press listener package: "
+                    + getCallingPackageName(mOnVolumeKeyLongPressListenerUid));
+            pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
+            pw.println(indent + "Media key listener package: "
+                    + getCallingPackageName(mOnMediaKeyListenerUid));
+            pw.println(indent + "Callback: " + mCallback);
+            pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
+            pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
+            pw.println(indent + "Restored MediaButtonReceiverComponentType: "
+                    + mRestoredMediaButtonReceiverComponentType);
+            mPriorityStack.dump(pw, indent);
+            pw.println(indent + "Session2Tokens:");
+            for (int i = 0; i < mSession2TokensPerUser.size(); i++) {
+                List<Session2Token> list = mSession2TokensPerUser.valueAt(i);
+                if (list == null || list.size() == 0) {
+                    continue;
+                }
+                for (Session2Token token : list) {
+                    pw.println(indent + "  " + token);
+                }
+            }
+        }
+
+        @Override
+        public void onMediaButtonSessionChanged(MediaSessionRecord oldMediaButtonSession,
+                MediaSessionRecord newMediaButtonSession) {
+            if (DEBUG_KEY_EVENT) {
+                Log.d(TAG, "Media button session is changed to " + newMediaButtonSession);
+            }
+            synchronized (mLock) {
+                if (oldMediaButtonSession != null) {
+                    mHandler.postSessionsChanged(oldMediaButtonSession.getUserId());
+                }
+                if (newMediaButtonSession != null) {
+                    rememberMediaButtonReceiverLocked(newMediaButtonSession);
+                    mHandler.postSessionsChanged(newMediaButtonSession.getUserId());
+                }
+                pushAddressedPlayerChangedLocked();
+            }
+        }
+
+        // Remember media button receiver and keep it in the persistent storage.
+        public void rememberMediaButtonReceiverLocked(MediaSessionRecord record) {
+            PendingIntent receiver = record.getMediaButtonReceiver();
+            mLastMediaButtonReceiver = receiver;
+            mRestoredMediaButtonReceiver = null;
+            mRestoredMediaButtonReceiverComponentType = COMPONENT_TYPE_INVALID;
+
+            String mediaButtonReceiverInfo = "";
+            if (receiver != null) {
+                ComponentName component = receiver.getIntent().getComponent();
+                if (component != null
+                        && record.getPackageName().equals(component.getPackageName())) {
+                    String componentName = component.flattenToString();
+                    int componentType = getComponentType(component);
+                    mediaButtonReceiverInfo = String.join(COMPONENT_NAME_USER_ID_DELIM,
+                            componentName, String.valueOf(record.getUserId()),
+                            String.valueOf(componentType));
+                }
+            }
+            Settings.Secure.putStringForUser(mContentResolver,
+                    Settings.System.MEDIA_BUTTON_RECEIVER, mediaButtonReceiverInfo,
+                    mFullUserId);
+        }
+
+        private void pushAddressedPlayerChangedLocked() {
+            if (mCallback == null) {
+                return;
+            }
+            try {
+                MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
+                if (mediaButtonSession != null) {
+                    mCallback.onAddressedPlayerChangedToMediaSession(
+                            new MediaSession.Token(mediaButtonSession.getControllerBinder()));
+                } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
+                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+                            mCurrentFullUserRecord.mLastMediaButtonReceiver
+                                    .getIntent().getComponent());
+                } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
+                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+                            mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
+                }
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to pushAddressedPlayerChangedLocked", e);
+            }
+        }
+
+        private MediaSessionRecord getMediaButtonSessionLocked() {
+            return isGlobalPriorityActiveLocked()
+                    ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
+        }
+
+        private int getComponentType(@Nullable ComponentName componentName) {
+            if (componentName == null) {
+                return COMPONENT_TYPE_INVALID;
+            }
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                ActivityInfo activityInfo = pm.getActivityInfo(componentName,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                | PackageManager.GET_ACTIVITIES);
+                if (activityInfo != null) {
+                    return COMPONENT_TYPE_ACTIVITY;
+                }
+            } catch (NameNotFoundException e) {
+            }
+            try {
+                ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                | PackageManager.GET_SERVICES);
+                if (serviceInfo != null) {
+                    return COMPONENT_TYPE_SERVICE;
+                }
+            } catch (NameNotFoundException e) {
+            }
+            // Pick legacy behavior for BroadcastReceiver or unknown.
+            return COMPONENT_TYPE_BROADCAST;
+        }
+    }
+
+    final class SessionsListenerRecord implements IBinder.DeathRecipient {
+        public final IActiveSessionsListener listener;
+        public final ComponentName componentName;
+        public final int userId;
+        public final int pid;
+        public final int uid;
+
+        SessionsListenerRecord(IActiveSessionsListener listener,
+                ComponentName componentName,
+                int userId, int pid, int uid) {
+            this.listener = listener;
+            this.componentName = componentName;
+            this.userId = userId;
+            this.pid = pid;
+            this.uid = uid;
+        }
+
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                mSessionsListeners.remove(this);
+            }
+        }
+    }
+
+    final class Session2TokensListenerRecord implements IBinder.DeathRecipient {
+        public final ISession2TokensListener listener;
+        public final int userId;
+
+        Session2TokensListenerRecord(ISession2TokensListener listener,
+                int userId) {
+            this.listener = listener;
+            this.userId = userId;
+        }
+
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                mSession2TokensListenerRecords.remove(this);
+            }
+        }
+    }
+
+    final class SettingsObserver extends ContentObserver {
+        private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+
+        private SettingsObserver() {
+            super(null);
+        }
+
+        private void observe() {
+            mContentResolver.registerContentObserver(mSecureSettingsUri,
+                    false, this, USER_ALL);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updateActiveSessionListeners();
+        }
+    }
+
+    class SessionManagerImpl extends ISessionManager.Stub {
+        private static final String EXTRA_WAKELOCK_ACQUIRED =
+                "android.media.AudioService.WAKELOCK_ACQUIRED";
+        private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
+
+        private boolean mVoiceButtonDown = false;
+        private boolean mVoiceButtonHandled = false;
+
+        @Override
+        public ISession createSession(String packageName, SessionCallbackLink cb, String tag,
+                int userId) throws RemoteException {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                enforcePackageName(packageName, uid);
+                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+                        false /* allowAll */, true /* requireFull */, "createSession", packageName);
+                if (cb == null) {
+                    throw new IllegalArgumentException("Controller callback cannot be null");
+                }
+                return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag)
+                        .getSessionBinder();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void notifySession2Created(Session2Token sessionToken) throws RemoteException {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "Session2 is created " + sessionToken);
+                }
+                if (uid != sessionToken.getUid()) {
+                    throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
+                            + " but actually=" + sessionToken.getUid());
+                }
+                Controller2Callback callback = new Controller2Callback(sessionToken);
+                // Note: It's safe not to keep controller here because it wouldn't be GC'ed until
+                //       it's closed.
+                // TODO: Keep controller as well for better readability
+                //       because the GC behavior isn't straightforward.
+                MediaController2 controller = new MediaController2(mContext, sessionToken,
+                        new HandlerExecutor(mHandler), callback);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public List<IBinder> getSessions(ComponentName componentName, int userId) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
+                ArrayList<IBinder> binders = new ArrayList<IBinder>();
+                synchronized (mLock) {
+                    List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
+                    for (MediaSessionRecord record : records) {
+                        binders.add(record.getControllerBinder().asBinder());
+                    }
+                }
+                return binders;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public List<Session2Token> getSession2Tokens(int userId) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                // Check that they can make calls on behalf of the user and
+                // get the final user id
+                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+                        true /* allowAll */, true /* requireFull */, "getSession2Tokens",
+                        null /* optional packageName */);
+                List<Session2Token> result;
+                synchronized (mLock) {
+                    result = getSession2TokensLocked(resolvedUserId);
+                }
+                return result;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void addSessionsListener(IActiveSessionsListener listener,
+                ComponentName componentName, int userId) throws RemoteException {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
+                synchronized (mLock) {
+                    int index = findIndexOfSessionsListenerLocked(listener);
+                    if (index != -1) {
+                        Log.w(TAG, "ActiveSessionsListener is already added, ignoring");
+                        return;
+                    }
+                    SessionsListenerRecord record = new SessionsListenerRecord(listener,
+                            componentName, resolvedUserId, pid, uid);
+                    try {
+                        listener.asBinder().linkToDeath(record, 0);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "ActiveSessionsListener is dead, ignoring it", e);
+                        return;
+                    }
+                    mSessionsListeners.add(record);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void removeSessionsListener(IActiveSessionsListener listener)
+                throws RemoteException {
+            synchronized (mLock) {
+                int index = findIndexOfSessionsListenerLocked(listener);
+                if (index != -1) {
+                    SessionsListenerRecord record = mSessionsListeners.remove(index);
+                    try {
+                        record.listener.asBinder().unlinkToDeath(record, 0);
+                    } catch (Exception e) {
+                        // ignore exceptions, the record is being removed
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void addSession2TokensListener(ISession2TokensListener listener,
+                int userId) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                // Check that they can make calls on behalf of the user and get the final user id.
+                int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+                        true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
+                        null /* optional packageName */);
+                synchronized (mLock) {
+                    int index = findIndexOfSession2TokensListenerLocked(listener);
+                    if (index >= 0) {
+                        Log.w(TAG, "addSession2TokensListener is already added, ignoring");
+                        return;
+                    }
+                    mSession2TokensListenerRecords.add(
+                            new Session2TokensListenerRecord(listener, resolvedUserId));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void removeSession2TokensListener(ISession2TokensListener listener) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            try {
+                synchronized (mLock) {
+                    int index = findIndexOfSession2TokensListenerLocked(listener);
+                    if (index >= 0) {
+                        Session2TokensListenerRecord listenerRecord =
+                                mSession2TokensListenerRecords.remove(index);
+                        try {
+                            listenerRecord.listener.asBinder().unlinkToDeath(listenerRecord, 0);
+                        } catch (Exception e) {
+                            // Ignore exception.
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * Handles the dispatching of the media button events to one of the
+         * registered listeners, or if there was none, broadcast an
+         * ACTION_MEDIA_BUTTON intent to the rest of the system.
+         *
+         * @param packageName The caller package
+         * @param asSystemService {@code true} if the event sent to the session as if it was come
+         *          from the system service instead of the app process. This helps sessions to
+         *          distinguish between the key injection by the app and key events from the
+         *          hardware devices. Should be used only when the volume key events aren't handled
+         *          by foreground activity. {@code false} otherwise to tell session about the real
+         *          caller.
+         * @param keyEvent a non-null KeyEvent whose key code is one of the
+         *            supported media buttons
+         * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
+         *            while this key event is dispatched.
+         */
+        @Override
+        public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
+                KeyEvent keyEvent, boolean needWakeLock) {
+            if (keyEvent == null || !KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
+                Log.w(TAG, "Attempted to dispatch null or non-media key event.");
+                return;
+            }
+
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "dispatchMediaKeyEvent, pkg=" + packageName + " pid=" + pid
+                            + ", uid=" + uid + ", asSystem=" + asSystemService + ", event="
+                            + keyEvent);
+                }
+                if (!isUserSetupComplete()) {
+                    // Global media key handling can have the side-effect of starting new
+                    // activities which is undesirable while setup is in progress.
+                    Slog.i(TAG, "Not dispatching media key event because user "
+                            + "setup is in progress.");
+                    return;
+                }
+
+                synchronized (mLock) {
+                    boolean isGlobalPriorityActive = isGlobalPriorityActiveLocked();
+                    if (isGlobalPriorityActive && uid != Process.SYSTEM_UID) {
+                        // Prevent dispatching key event through reflection while the global
+                        // priority session is active.
+                        Slog.i(TAG, "Only the system can dispatch media key event "
+                                + "to the global priority session.");
+                        return;
+                    }
+                    if (!isGlobalPriorityActive) {
+                        if (mCurrentFullUserRecord.mOnMediaKeyListener != null) {
+                            if (DEBUG_KEY_EVENT) {
+                                Log.d(TAG, "Send " + keyEvent + " to the media key listener");
+                            }
+                            try {
+                                mCurrentFullUserRecord.mOnMediaKeyListener.onMediaKey(keyEvent,
+                                        new MediaKeyListenerResultReceiver(packageName, pid, uid,
+                                                asSystemService, keyEvent, needWakeLock));
+                                return;
+                            } catch (RemoteException e) {
+                                Log.w(TAG, "Failed to send " + keyEvent
+                                        + " to the media key listener");
+                            }
+                        }
+                    }
+                    if (!isGlobalPriorityActive && isVoiceKey(keyEvent.getKeyCode())) {
+                        handleVoiceKeyEventLocked(packageName, pid, uid, asSystemService, keyEvent,
+                                needWakeLock);
+                    } else {
+                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+                                keyEvent, needWakeLock);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void setCallback(ICallback callback) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
+                    throw new SecurityException("Only Bluetooth service processes can set"
+                            + " Callback");
+                }
+                synchronized (mLock) {
+                    int userId = UserHandle.getUserId(uid);
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can set the callback"
+                                + ", userId=" + userId);
+                        return;
+                    }
+                    user.mCallback = callback;
+                    Log.d(TAG, "The callback " + user.mCallback
+                            + " is set by " + getCallingPackageName(uid));
+                    if (user.mCallback == null) {
+                        return;
+                    }
+                    try {
+                        user.mCallback.asBinder().linkToDeath(
+                                new IBinder.DeathRecipient() {
+                                    @Override
+                                    public void binderDied() {
+                                        synchronized (mLock) {
+                                            user.mCallback = null;
+                                        }
+                                    }
+                                }, 0);
+                        user.pushAddressedPlayerChangedLocked();
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to set callback", e);
+                        user.mCallback = null;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void setOnVolumeKeyLongPressListener(IOnVolumeKeyLongPressListener listener) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // Enforce SET_VOLUME_KEY_LONG_PRESS_LISTENER permission.
+                if (mContext.checkPermission(
+                        android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER, pid, uid)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    throw new SecurityException("Must hold the SET_VOLUME_KEY_LONG_PRESS_LISTENER"
+                            + " permission.");
+                }
+
+                synchronized (mLock) {
+                    int userId = UserHandle.getUserId(uid);
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can set the volume key long-press listener"
+                                + ", userId=" + userId);
+                        return;
+                    }
+                    if (user.mOnVolumeKeyLongPressListener != null
+                            && user.mOnVolumeKeyLongPressListenerUid != uid) {
+                        Log.w(TAG, "The volume key long-press listener cannot be reset"
+                                + " by another app , mOnVolumeKeyLongPressListener="
+                                + user.mOnVolumeKeyLongPressListenerUid
+                                + ", uid=" + uid);
+                        return;
+                    }
+
+                    user.mOnVolumeKeyLongPressListener = listener;
+                    user.mOnVolumeKeyLongPressListenerUid = uid;
+
+                    Log.d(TAG, "The volume key long-press listener "
+                            + listener + " is set by " + getCallingPackageName(uid));
+
+                    if (user.mOnVolumeKeyLongPressListener != null) {
+                        try {
+                            user.mOnVolumeKeyLongPressListener.asBinder().linkToDeath(
+                                    new IBinder.DeathRecipient() {
+                                        @Override
+                                        public void binderDied() {
+                                            synchronized (mLock) {
+                                                user.mOnVolumeKeyLongPressListener = null;
+                                            }
+                                        }
+                                    }, 0);
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Failed to set death recipient "
+                                    + user.mOnVolumeKeyLongPressListener);
+                            user.mOnVolumeKeyLongPressListener = null;
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void setOnMediaKeyListener(IOnMediaKeyListener listener) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // Enforce SET_MEDIA_KEY_LISTENER permission.
+                if (mContext.checkPermission(
+                        android.Manifest.permission.SET_MEDIA_KEY_LISTENER, pid, uid)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    throw new SecurityException("Must hold the SET_MEDIA_KEY_LISTENER permission.");
+                }
+
+                synchronized (mLock) {
+                    int userId = UserHandle.getUserId(uid);
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can set the media key listener"
+                                + ", userId=" + userId);
+                        return;
+                    }
+                    if (user.mOnMediaKeyListener != null && user.mOnMediaKeyListenerUid != uid) {
+                        Log.w(TAG, "The media key listener cannot be reset by another app. "
+                                + ", mOnMediaKeyListenerUid=" + user.mOnMediaKeyListenerUid
+                                + ", uid=" + uid);
+                        return;
+                    }
+
+                    user.mOnMediaKeyListener = listener;
+                    user.mOnMediaKeyListenerUid = uid;
+
+                    Log.d(TAG, "The media key listener " + user.mOnMediaKeyListener
+                            + " is set by " + getCallingPackageName(uid));
+
+                    if (user.mOnMediaKeyListener != null) {
+                        try {
+                            user.mOnMediaKeyListener.asBinder().linkToDeath(
+                                    new IBinder.DeathRecipient() {
+                                        @Override
+                                        public void binderDied() {
+                                            synchronized (mLock) {
+                                                user.mOnMediaKeyListener = null;
+                                            }
+                                        }
+                                    }, 0);
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Failed to set death recipient " + user.mOnMediaKeyListener);
+                            user.mOnMediaKeyListener = null;
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        /**
+         * Handles the dispatching of the volume button events to one of the
+         * registered listeners. If there's a volume key long-press listener and
+         * there's no active global priority session, long-pressess will be sent to the
+         * long-press listener instead of adjusting volume.
+         *
+         * @param packageName The caller's package name, obtained by Context#getPackageName()
+         * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
+         * @param asSystemService {@code true} if the event sent to the session as if it was come
+         *          from the system service instead of the app process. This helps sessions to
+         *          distinguish between the key injection by the app and key events from the
+         *          hardware devices. Should be used only when the volume key events aren't handled
+         *          by foreground activity. {@code false} otherwise to tell session about the real
+         *          caller.
+         * @param keyEvent a non-null KeyEvent whose key code is one of the
+         *            {@link KeyEvent#KEYCODE_VOLUME_UP},
+         *            {@link KeyEvent#KEYCODE_VOLUME_DOWN},
+         *            or {@link KeyEvent#KEYCODE_VOLUME_MUTE}.
+         * @param stream stream type to adjust volume.
+         * @param musicOnly true if both UI nor haptic feedback aren't needed when adjust volume.
+         */
+        @Override
+        public void dispatchVolumeKeyEvent(String packageName, String opPackageName,
+                boolean asSystemService, KeyEvent keyEvent, int stream, boolean musicOnly) {
+            if (keyEvent == null
+                    || (keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_UP
+                            && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_DOWN
+                            && keyEvent.getKeyCode() != KeyEvent.KEYCODE_VOLUME_MUTE)) {
+                Log.w(TAG, "Attempted to dispatch null or non-volume key event.");
+                return;
+            }
+
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+
+            if (DEBUG_KEY_EVENT) {
+                Log.d(TAG, "dispatchVolumeKeyEvent, pkg=" + packageName + ", pid=" + pid + ", uid="
+                        + uid + ", asSystem=" + asSystemService + ", event=" + keyEvent);
+            }
+
+            try {
+                synchronized (mLock) {
+                    if (isGlobalPriorityActiveLocked()
+                            || mCurrentFullUserRecord.mOnVolumeKeyLongPressListener == null) {
+                        dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+                                asSystemService, keyEvent, stream, musicOnly);
+                    } else {
+                        // TODO: Consider the case when both volume up and down keys are pressed
+                        //       at the same time.
+                        if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+                            if (keyEvent.getRepeatCount() == 0) {
+                                // Keeps the copy of the KeyEvent because it can be reused.
+                                mCurrentFullUserRecord.mInitialDownVolumeKeyEvent =
+                                        KeyEvent.obtain(keyEvent);
+                                mCurrentFullUserRecord.mInitialDownVolumeStream = stream;
+                                mCurrentFullUserRecord.mInitialDownMusicOnly = musicOnly;
+                                mHandler.sendMessageDelayed(
+                                        mHandler.obtainMessage(
+                                                MessageHandler.MSG_VOLUME_INITIAL_DOWN,
+                                                mCurrentFullUserRecord.mFullUserId, 0),
+                                        mLongPressTimeout);
+                            }
+                            if (keyEvent.getRepeatCount() > 0 || keyEvent.isLongPress()) {
+                                mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
+                                if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null) {
+                                    dispatchVolumeKeyLongPressLocked(
+                                            mCurrentFullUserRecord.mInitialDownVolumeKeyEvent);
+                                    // Mark that the key is already handled.
+                                    mCurrentFullUserRecord.mInitialDownVolumeKeyEvent = null;
+                                }
+                                dispatchVolumeKeyLongPressLocked(keyEvent);
+                            }
+                        } else { // if up
+                            mHandler.removeMessages(MessageHandler.MSG_VOLUME_INITIAL_DOWN);
+                            if (mCurrentFullUserRecord.mInitialDownVolumeKeyEvent != null
+                                    && mCurrentFullUserRecord.mInitialDownVolumeKeyEvent
+                                    .getDownTime() == keyEvent.getDownTime()) {
+                                // Short-press. Should change volume.
+                                dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+                                        asSystemService,
+                                        mCurrentFullUserRecord.mInitialDownVolumeKeyEvent,
+                                        mCurrentFullUserRecord.mInitialDownVolumeStream,
+                                        mCurrentFullUserRecord.mInitialDownMusicOnly);
+                                dispatchVolumeKeyEventLocked(packageName, opPackageName, pid, uid,
+                                        asSystemService, keyEvent, stream, musicOnly);
+                            } else {
+                                dispatchVolumeKeyLongPressLocked(keyEvent);
+                            }
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        private void dispatchVolumeKeyEventLocked(String packageName, String opPackageName, int pid,
+                int uid, boolean asSystemService, KeyEvent keyEvent, int stream,
+                boolean musicOnly) {
+            boolean down = keyEvent.getAction() == KeyEvent.ACTION_DOWN;
+            boolean up = keyEvent.getAction() == KeyEvent.ACTION_UP;
+            int direction = 0;
+            boolean isMute = false;
+            switch (keyEvent.getKeyCode()) {
+                case KeyEvent.KEYCODE_VOLUME_UP:
+                    direction = AudioManager.ADJUST_RAISE;
+                    break;
+                case KeyEvent.KEYCODE_VOLUME_DOWN:
+                    direction = AudioManager.ADJUST_LOWER;
+                    break;
+                case KeyEvent.KEYCODE_VOLUME_MUTE:
+                    isMute = true;
+                    break;
+            }
+            if (down || up) {
+                int flags = AudioManager.FLAG_FROM_KEY;
+                if (musicOnly) {
+                    // This flag is used when the screen is off to only affect active media.
+                    flags |= AudioManager.FLAG_ACTIVE_MEDIA_ONLY;
+                } else {
+                    // These flags are consistent with the home screen
+                    if (up) {
+                        flags |= AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
+                    } else {
+                        flags |= AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
+                    }
+                }
+                if (direction != 0) {
+                    // If this is action up we want to send a beep for non-music events
+                    if (up) {
+                        direction = 0;
+                    }
+                    dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+                            asSystemService, stream, direction, flags);
+                } else if (isMute) {
+                    if (down && keyEvent.getRepeatCount() == 0) {
+                        dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid,
+                                asSystemService, stream, AudioManager.ADJUST_TOGGLE_MUTE, flags);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void dispatchAdjustVolume(String packageName, String opPackageName,
+                int suggestedStream, int delta, int flags) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    dispatchAdjustVolumeLocked(packageName, opPackageName, pid, uid, false,
+                            suggestedStream, delta, flags);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void setRemoteVolumeController(IRemoteVolumeController rvc) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                enforceSystemUiPermission("listen for volume changes", pid, uid);
+                mRvc = rvc;
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isGlobalPriorityActive() {
+            synchronized (mLock) {
+                return isGlobalPriorityActiveLocked();
+            }
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
+            pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
+            pw.println();
+
+            synchronized (mLock) {
+                pw.println(mSessionsListeners.size() + " sessions listeners.");
+                pw.println("Global priority session is " + mGlobalPrioritySession);
+                if (mGlobalPrioritySession != null) {
+                    mGlobalPrioritySession.dump(pw, "  ");
+                }
+                pw.println("User Records:");
+                int count = mUserRecords.size();
+                for (int i = 0; i < count; i++) {
+                    mUserRecords.valueAt(i).dumpLocked(pw, "");
+                }
+                mAudioPlayerStateMonitor.dump(mContext, pw, "");
+            }
+        }
+
+        /**
+         * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
+         * permission or an enabled notification listener)
+         *
+         * @param controllerPackageName package name of the controller app
+         * @param controllerPid pid of the controller app
+         * @param controllerUid uid of the controller app
+         */
+        @Override
+        public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
+                throws RemoteException {
+            final int uid = Binder.getCallingUid();
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // Don't perform sanity check between controllerPackageName and controllerUid.
+                // When an (activity|service) runs on the another apps process by specifying
+                // android:process in the AndroidManifest.xml, then PID and UID would have the
+                // running process' information instead of the (activity|service) that has created
+                // MediaController.
+                // Note that we can use Context#getOpPackageName() instead of
+                // Context#getPackageName() for getting package name that matches with the PID/UID,
+                // but it doesn't tell which package has created the MediaController, so useless.
+                return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
+                        controllerPid, controllerUid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        // For MediaSession
+        private int verifySessionsRequest(ComponentName componentName, int userId, final int pid,
+                final int uid) {
+            String packageName = null;
+            if (componentName != null) {
+                // If they gave us a component name verify they own the
+                // package
+                packageName = componentName.getPackageName();
+                enforcePackageName(packageName, uid);
+            }
+            // Check that they can make calls on behalf of the user and
+            // get the final user id
+            int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
+                    true /* allowAll */, true /* requireFull */, "getSessions", packageName);
+            // Check if they have the permissions or their component is
+            // enabled for the user they're calling from.
+            enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
+            return resolvedUserId;
+        }
+
+        private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
+                int pid, int uid) throws RemoteException {
+            // Allow API calls from the System UI
+            if (isCurrentVolumeController(pid, uid)) {
+                return true;
+            }
+
+            // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+            // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+            // check here.
+            if (uid == Process.SYSTEM_UID || mContext.checkPermission(
+                    android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+                    == PackageManager.PERMISSION_GRANTED) {
+                return true;
+            } else if (DEBUG) {
+                Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+            }
+
+            // You may not access another user's content as an enabled listener.
+            final int userId = UserHandle.getUserId(uid);
+            if (resolvedUserId != userId) {
+                return false;
+            }
+
+            // TODO(jaewan): (Post-P) Propose NotificationManager#hasEnabledNotificationListener(
+            //               String pkgName) to notification team for optimization
+            final List<ComponentName> enabledNotificationListeners =
+                    mNotificationManager.getEnabledNotificationListeners(userId);
+            if (enabledNotificationListeners != null) {
+                for (int i = 0; i < enabledNotificationListeners.size(); i++) {
+                    if (TextUtils.equals(packageName,
+                            enabledNotificationListeners.get(i).getPackageName())) {
+                        return true;
+                    }
+                }
+            }
+            if (DEBUG) {
+                Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
+                        + "notification listener");
+            }
+            return false;
+        }
+
+        private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
+                int uid, boolean asSystemService, int suggestedStream, int direction, int flags) {
+            MediaSessionRecord session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
+                    : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();
+
+            boolean preferSuggestedStream = false;
+            if (isValidLocalStreamType(suggestedStream)
+                    && AudioSystem.isStreamActive(suggestedStream, 0)) {
+                preferSuggestedStream = true;
+            }
+            if (DEBUG_KEY_EVENT) {
+                Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
+                        + flags + ", suggestedStream=" + suggestedStream
+                        + ", preferSuggestedStream=" + preferSuggestedStream);
+            }
+            if (session == null || preferSuggestedStream) {
+                if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
+                        && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
+                    if (DEBUG) {
+                        Log.d(TAG, "No active session to adjust, skipping media only volume event");
+                    }
+                    return;
+                }
+
+                // Execute mAudioService.adjustSuggestedStreamVolume() on
+                // handler thread of MediaSessionService.
+                // This will release the MediaSessionService.mLock sooner and avoid
+                // a potential deadlock between MediaSessionService.mLock and
+                // ActivityManagerService lock.
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        final String callingOpPackageName;
+                        final int callingUid;
+                        if (asSystemService) {
+                            callingOpPackageName = mContext.getOpPackageName();
+                            callingUid = Process.myUid();
+                        } else {
+                            callingOpPackageName = opPackageName;
+                            callingUid = uid;
+                        }
+                        try {
+                            mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream,
+                                    direction, flags, callingOpPackageName, callingUid);
+                        } catch (SecurityException | IllegalArgumentException e) {
+                            Log.e(TAG, "Cannot adjust volume: direction=" + direction
+                                    + ", suggestedStream=" + suggestedStream + ", flags=" + flags
+                                    + ", packageName=" + packageName + ", uid=" + uid
+                                    + ", asSystemService=" + asSystemService, e);
+                        }
+                    }
+                });
+            } else {
+                session.adjustVolume(packageName, opPackageName, pid, uid, null, asSystemService,
+                        direction, flags, true);
+            }
+        }
+
+        private void handleVoiceKeyEventLocked(String packageName, int pid, int uid,
+                boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+            int action = keyEvent.getAction();
+            boolean isLongPress = (keyEvent.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0;
+            if (action == KeyEvent.ACTION_DOWN) {
+                if (keyEvent.getRepeatCount() == 0) {
+                    mVoiceButtonDown = true;
+                    mVoiceButtonHandled = false;
+                } else if (mVoiceButtonDown && !mVoiceButtonHandled && isLongPress) {
+                    mVoiceButtonHandled = true;
+                    startVoiceInput(needWakeLock);
+                }
+            } else if (action == KeyEvent.ACTION_UP) {
+                if (mVoiceButtonDown) {
+                    mVoiceButtonDown = false;
+                    if (!mVoiceButtonHandled && !keyEvent.isCanceled()) {
+                        // Resend the down then send this event through
+                        KeyEvent downEvent = KeyEvent.changeAction(keyEvent, KeyEvent.ACTION_DOWN);
+                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+                                downEvent, needWakeLock);
+                        dispatchMediaKeyEventLocked(packageName, pid, uid, asSystemService,
+                                keyEvent, needWakeLock);
+                    }
+                }
+            }
+        }
+
+        private void dispatchMediaKeyEventLocked(String packageName, int pid, int uid,
+                boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+            MediaSessionRecord session = mCurrentFullUserRecord.getMediaButtonSessionLocked();
+            if (session != null) {
+                if (DEBUG_KEY_EVENT) {
+                    Log.d(TAG, "Sending " + keyEvent + " to " + session);
+                }
+                if (needWakeLock) {
+                    mKeyEventReceiver.aquireWakeLockLocked();
+                }
+                // If we don't need a wakelock use -1 as the id so we won't release it later.
+                session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
+                        needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+                        mKeyEventReceiver);
+                if (mCurrentFullUserRecord.mCallback != null) {
+                    try {
+                        mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
+                                keyEvent, new MediaSession.Token(session.getControllerBinder()));
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to send callback", e);
+                    }
+                }
+            } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
+                    || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
+                if (needWakeLock) {
+                    mKeyEventReceiver.aquireWakeLockLocked();
+                }
+                Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+                mediaButtonIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+                // TODO: Find a way to also send PID/UID in secure way.
+                String callerPackageName =
+                        (asSystemService) ? mContext.getPackageName() : packageName;
+                mediaButtonIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callerPackageName);
+                try {
+                    if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
+                        PendingIntent receiver = mCurrentFullUserRecord.mLastMediaButtonReceiver;
+                        if (DEBUG_KEY_EVENT) {
+                            Log.d(TAG, "Sending " + keyEvent
+                                    + " to the last known PendingIntent " + receiver);
+                        }
+                        receiver.send(mContext,
+                                needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
+                                mediaButtonIntent, mKeyEventReceiver, mHandler);
+                        if (mCurrentFullUserRecord.mCallback != null) {
+                            ComponentName componentName = mCurrentFullUserRecord
+                                    .mLastMediaButtonReceiver.getIntent().getComponent();
+                            if (componentName != null) {
+                                mCurrentFullUserRecord.mCallback
+                                        .onMediaKeyEventDispatchedToMediaButtonReceiver(
+                                                keyEvent, componentName);
+                            }
+                        }
+                    } else {
+                        ComponentName receiver =
+                                mCurrentFullUserRecord.mRestoredMediaButtonReceiver;
+                        int componentType = mCurrentFullUserRecord
+                                .mRestoredMediaButtonReceiverComponentType;
+                        UserHandle userHandle = UserHandle.of(mCurrentFullUserRecord
+                                .mRestoredMediaButtonReceiverUserId);
+                        if (DEBUG_KEY_EVENT) {
+                            Log.d(TAG, "Sending " + keyEvent + " to the restored intent "
+                                    + receiver + ", type=" + componentType);
+                        }
+                        mediaButtonIntent.setComponent(receiver);
+                        try {
+                            switch (componentType) {
+                                case FullUserRecord.COMPONENT_TYPE_ACTIVITY:
+                                    mContext.startActivityAsUser(mediaButtonIntent, userHandle);
+                                    break;
+                                case FullUserRecord.COMPONENT_TYPE_SERVICE:
+                                    mContext.startForegroundServiceAsUser(mediaButtonIntent,
+                                            userHandle);
+                                    break;
+                                default:
+                                    // Legacy behavior for other cases.
+                                    mContext.sendBroadcastAsUser(mediaButtonIntent, userHandle);
+                            }
+                        } catch (Exception e) {
+                            Log.w(TAG, "Error sending media button to the restored intent "
+                                    + receiver + ", type=" + componentType, e);
+                        }
+                        if (mCurrentFullUserRecord.mCallback != null) {
+                            mCurrentFullUserRecord.mCallback
+                                    .onMediaKeyEventDispatchedToMediaButtonReceiver(
+                                            keyEvent, receiver);
+                        }
+                    }
+                } catch (CanceledException e) {
+                    Log.i(TAG, "Error sending key event to media button receiver "
+                            + mCurrentFullUserRecord.mLastMediaButtonReceiver, e);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Failed to send callback", e);
+                }
+            }
+        }
+
+        private void startVoiceInput(boolean needWakeLock) {
+            Intent voiceIntent = null;
+            // select which type of search to launch:
+            // - screen on and device unlocked: action is ACTION_WEB_SEARCH
+            // - device locked or screen off: action is
+            // ACTION_VOICE_SEARCH_HANDS_FREE
+            // with EXTRA_SECURE set to true if the device is securely locked
+            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+            boolean isLocked = mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
+            if (!isLocked && pm.isScreenOn()) {
+                voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH);
+                Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH");
+            } else {
+                voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
+                voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE,
+                        isLocked && mKeyguardManager.isKeyguardSecure());
+                Log.i(TAG, "voice-based interactions: about to use ACTION_VOICE_SEARCH_HANDS_FREE");
+            }
+            // start the search activity
+            if (needWakeLock) {
+                mMediaEventWakeLock.acquire();
+            }
+            try {
+                if (voiceIntent != null) {
+                    voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                    if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
+                    mContext.startActivityAsUser(voiceIntent, UserHandle.CURRENT);
+                }
+            } catch (ActivityNotFoundException e) {
+                Log.w(TAG, "No activity for search: " + e);
+            } finally {
+                if (needWakeLock) {
+                    mMediaEventWakeLock.release();
+                }
+            }
+        }
+
+        private boolean isVoiceKey(int keyCode) {
+            return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
+                    || (!mHasFeatureLeanback && keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
+        }
+
+        private boolean isUserSetupComplete() {
+            return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+        }
+
+        // we only handle public stream types, which are 0-5
+        private boolean isValidLocalStreamType(int streamType) {
+            return streamType >= AudioManager.STREAM_VOICE_CALL
+                    && streamType <= AudioManager.STREAM_NOTIFICATION;
+        }
+
+        private class MediaKeyListenerResultReceiver extends ResultReceiver implements Runnable {
+            private final String mPackageName;
+            private final int mPid;
+            private final int mUid;
+            private final boolean mAsSystemService;
+            private final KeyEvent mKeyEvent;
+            private final boolean mNeedWakeLock;
+            private boolean mHandled;
+
+            private MediaKeyListenerResultReceiver(String packageName, int pid, int uid,
+                    boolean asSystemService, KeyEvent keyEvent, boolean needWakeLock) {
+                super(mHandler);
+                mHandler.postDelayed(this, MEDIA_KEY_LISTENER_TIMEOUT);
+                mPackageName = packageName;
+                mPid = pid;
+                mUid = uid;
+                mAsSystemService = asSystemService;
+                mKeyEvent = keyEvent;
+                mNeedWakeLock = needWakeLock;
+            }
+
+            @Override
+            public void run() {
+                Log.d(TAG, "The media key listener is timed-out for " + mKeyEvent);
+                dispatchMediaKeyEvent();
+            }
+
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                if (resultCode == MediaSessionManager.RESULT_MEDIA_KEY_HANDLED) {
+                    mHandled = true;
+                    mHandler.removeCallbacks(this);
+                    return;
+                }
+                dispatchMediaKeyEvent();
+            }
+
+            private void dispatchMediaKeyEvent() {
+                if (mHandled) {
+                    return;
+                }
+                mHandled = true;
+                mHandler.removeCallbacks(this);
+                synchronized (mLock) {
+                    if (!isGlobalPriorityActiveLocked()
+                            && isVoiceKey(mKeyEvent.getKeyCode())) {
+                        handleVoiceKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
+                                mKeyEvent, mNeedWakeLock);
+                    } else {
+                        dispatchMediaKeyEventLocked(mPackageName, mPid, mUid, mAsSystemService,
+                                mKeyEvent, mNeedWakeLock);
+                    }
+                }
+            }
+        }
+
+        private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler);
+
+        class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable,
+                PendingIntent.OnFinished {
+            private final Handler mHandler;
+            private int mRefCount = 0;
+            private int mLastTimeoutId = 0;
+
+            KeyEventWakeLockReceiver(Handler handler) {
+                super(handler);
+                mHandler = handler;
+            }
+
+            public void onTimeout() {
+                synchronized (mLock) {
+                    if (mRefCount == 0) {
+                        // We've already released it, so just return
+                        return;
+                    }
+                    mLastTimeoutId++;
+                    mRefCount = 0;
+                    releaseWakeLockLocked();
+                }
+            }
+
+            public void aquireWakeLockLocked() {
+                if (mRefCount == 0) {
+                    mMediaEventWakeLock.acquire();
+                }
+                mRefCount++;
+                mHandler.removeCallbacks(this);
+                mHandler.postDelayed(this, WAKELOCK_TIMEOUT);
+
+            }
+
+            @Override
+            public void run() {
+                onTimeout();
+            }
+
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                if (resultCode < mLastTimeoutId) {
+                    // Ignore results from calls that were before the last
+                    // timeout, just in case.
+                    return;
+                } else {
+                    synchronized (mLock) {
+                        if (mRefCount > 0) {
+                            mRefCount--;
+                            if (mRefCount == 0) {
+                                releaseWakeLockLocked();
+                            }
+                        }
+                    }
+                }
+            }
+
+            private void releaseWakeLockLocked() {
+                mMediaEventWakeLock.release();
+                mHandler.removeCallbacks(this);
+            }
+
+            @Override
+            public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
+                    String resultData, Bundle resultExtras) {
+                onReceiveResult(resultCode, null);
+            }
+        };
+
+        BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent == null) {
+                    return;
+                }
+                Bundle extras = intent.getExtras();
+                if (extras == null) {
+                    return;
+                }
+                synchronized (mLock) {
+                    if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
+                            && mMediaEventWakeLock.isHeld()) {
+                        mMediaEventWakeLock.release();
+                    }
+                }
+            }
+        };
+    }
+
+    final class MessageHandler extends Handler {
+        private static final int MSG_SESSIONS_CHANGED = 1;
+        private static final int MSG_VOLUME_INITIAL_DOWN = 2;
+        private final SparseArray<Integer> mIntegerCache = new SparseArray<>();
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SESSIONS_CHANGED:
+                    pushSessionsChanged((int) msg.obj);
+                    break;
+                case MSG_VOLUME_INITIAL_DOWN:
+                    synchronized (mLock) {
+                        FullUserRecord user = mUserRecords.get((int) msg.arg1);
+                        if (user != null && user.mInitialDownVolumeKeyEvent != null) {
+                            dispatchVolumeKeyLongPressLocked(user.mInitialDownVolumeKeyEvent);
+                            // Mark that the key is already handled.
+                            user.mInitialDownVolumeKeyEvent = null;
+                        }
+                    }
+                    break;
+            }
+        }
+
+        public void postSessionsChanged(int userId) {
+            // Use object instead of the arguments when posting message to remove pending requests.
+            Integer userIdInteger = mIntegerCache.get(userId);
+            if (userIdInteger == null) {
+                userIdInteger = Integer.valueOf(userId);
+                mIntegerCache.put(userId, userIdInteger);
+            }
+            removeMessages(MSG_SESSIONS_CHANGED, userIdInteger);
+            obtainMessage(MSG_SESSIONS_CHANGED, userIdInteger).sendToTarget();
+        }
+    }
+
+    private class Controller2Callback extends MediaController2.ControllerCallback {
+        private final Session2Token mToken;
+
+        Controller2Callback(Session2Token token) {
+            mToken = token;
+        }
+
+        @Override
+        public void onConnected(MediaController2 controller, Session2CommandGroup allowedCommands) {
+            synchronized (mLock) {
+                int userId = UserHandle.getUserId(mToken.getUid());
+                mSession2TokensPerUser.get(userId).add(mToken);
+                pushSession2TokensChangedLocked(userId);
+            }
+        }
+
+        @Override
+        public void onDisconnected(MediaController2 controller) {
+            synchronized (mLock) {
+                int userId = UserHandle.getUserId(mToken.getUid());
+                mSession2TokensPerUser.get(userId).remove(mToken);
+                pushSession2TokensChangedLocked(userId);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java b/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java
index 6a5f563..64c451d 100644
--- a/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java
+++ b/services/core/java/com/android/server/media/RemoteDisplayProviderWatcher.java
@@ -159,12 +159,13 @@
                     + serviceInfo.packageName + "/" + serviceInfo.name);
             return false;
         }
-        if (!hasCaptureVideoPermission(serviceInfo.packageName)) {
-            // If the service does not have permission to capture video then it
-            // isn't going to be terribly useful as a remote display, is it?
-            // Kind of makes you wonder what it's doing there in the first place.
+        if (mPackageManager.checkPermission(Manifest.permission.REMOTE_DISPLAY_PROVIDER,
+                        serviceInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
+            // If the service does not have this permission then the system will not bind to it.
+            // This is to prevent non privileged apps declaring themselves as remote display
+            // providers just to be bound to by the system and keep their process alive.
             Slog.w(TAG, "Ignoring remote display provider service because it does not "
-                    + "have the CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT "
+                    + "have the REMOTE_DISPLAY_PROVIDER "
                     + "permission: " + serviceInfo.packageName + "/" + serviceInfo.name);
             return false;
         }
@@ -172,18 +173,6 @@
         return true;
     }
 
-    private boolean hasCaptureVideoPermission(String packageName) {
-        if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT,
-                packageName) == PackageManager.PERMISSION_GRANTED) {
-            return true;
-        }
-        if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT,
-                packageName) == PackageManager.PERMISSION_GRANTED) {
-            return true;
-        }
-        return false;
-    }
-
     private int findProvider(String packageName, String className) {
         int count = mProviders.size();
         for (int i = 0; i < count; i++) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6932390..6fe32c5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1342,6 +1342,8 @@
     final @Nullable String mSystemTextClassifierPackage;
     final @Nullable String mWellbeingPackage;
     final @Nullable String mDocumenterPackage;
+    final @Nullable String mConfiguratorPackage;
+    final @Nullable String mAppPredictionServicePackage;
     final @NonNull String mServicesSystemSharedLibraryPackageName;
     final @NonNull String mSharedSystemSharedLibraryPackageName;
 
@@ -2865,6 +2867,9 @@
 
             mWellbeingPackage = getWellbeingPackageName();
             mDocumenterPackage = getDocumenterPackageName();
+            mConfiguratorPackage =
+                    mContext.getString(R.string.config_deviceConfiguratorPackageName);
+            mAppPredictionServicePackage = getAppPredictionServicePackageName();
 
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
@@ -3747,7 +3752,7 @@
     /**
      * Returns whether or not a full application can see an instant application.
      * <p>
-     * Currently, there are three cases in which this can occur:
+     * Currently, there are four cases in which this can occur:
      * <ol>
      * <li>The calling application is a "special" process. Special processes
      *     are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li>
@@ -3755,6 +3760,7 @@
      *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li>
      * <li>The calling application is the default launcher on the
      *     system partition.</li>
+     * <li>The calling application is the default app prediction service.</li>
      * </ol>
      */
     private boolean canViewInstantApps(int callingUid, int userId) {
@@ -3772,6 +3778,11 @@
                     && isCallerSameApp(homeComponent.getPackageName(), callingUid)) {
                 return true;
             }
+            // TODO(b/122900055) Change/Remove this and replace with new permission role.
+            if (mAppPredictionServicePackage != null
+                    && isCallerSameApp(mAppPredictionServicePackage, callingUid)) {
+                return true;
+            }
         }
         return false;
     }
@@ -5487,13 +5498,13 @@
         final int callingUserId = UserHandle.getUserId(callingUid);
         final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         // Map to base uids.
-        uid1 = UserHandle.getAppId(uid1);
-        uid2 = UserHandle.getAppId(uid2);
+        final int appId1 = UserHandle.getAppId(uid1);
+        final int appId2 = UserHandle.getAppId(uid2);
         // reader
         synchronized (mPackages) {
             Signature[] s1;
             Signature[] s2;
-            Object obj = mSettings.getSettingLPr(uid1);
+            Object obj = mSettings.getSettingLPr(appId1);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
                     if (isCallerInstantApp) {
@@ -5512,7 +5523,7 @@
             } else {
                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
             }
-            obj = mSettings.getSettingLPr(uid2);
+            obj = mSettings.getSettingLPr(appId2);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
                     if (isCallerInstantApp) {
@@ -5567,11 +5578,11 @@
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
         // Map to base uids.
-        uid = UserHandle.getAppId(uid);
+        final int appId = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
             final PackageParser.SigningDetails signingDetails;
-            final Object obj = mSettings.getSettingLPr(uid);
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
                     final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
@@ -5687,10 +5698,10 @@
         final int callingUid = Binder.getCallingUid();
         final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         final int userId = UserHandle.getUserId(uid);
-        uid = UserHandle.getAppId(uid);
+        final int appId = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(uid);
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj instanceof SharedUserSetting) {
                 if (isCallerInstantApp) {
                     return null;
@@ -5725,8 +5736,9 @@
         if (getInstantAppPackageName(callingUid) != null) {
             return null;
         }
+        final int appId = UserHandle.getAppId(uid);
         synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 return sus.name + ":" + sus.userId;
@@ -5753,8 +5765,8 @@
         final String[] names = new String[uids.length];
         synchronized (mPackages) {
             for (int i = uids.length - 1; i >= 0; i--) {
-                final int uid = uids[i];
-                Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+                final int appId = UserHandle.getAppId(uids[i]);
+                final Object obj = mSettings.getSettingLPr(appId);
                 if (obj instanceof SharedUserSetting) {
                     final SharedUserSetting sus = (SharedUserSetting) obj;
                     names[i] = "shared:" + sus.name;
@@ -5802,8 +5814,9 @@
         if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
+        final int appId = UserHandle.getAppId(uid);
         synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 return sus.pkgFlags;
@@ -5824,8 +5837,9 @@
         if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
+        final int appId = UserHandle.getAppId(uid);
         synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 return sus.pkgPrivateFlags;
@@ -5845,10 +5859,10 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
         }
-        uid = UserHandle.getAppId(uid);
+        final int appId = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(uid);
+            final Object obj = mSettings.getSettingLPr(appId);
             if (obj instanceof SharedUserSetting) {
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 final Iterator<PackageSetting> it = sus.packages.iterator();
@@ -13778,6 +13792,11 @@
                     ServiceManager.getService(Context.BACKUP_SERVICE));
             if (bm != null) {
                 int userId = args.user.getIdentifier();
+                // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM
+                // in the BackupManager. USER_ALL is used in compatibility tests.
+                if (userId == UserHandle.USER_ALL) {
+                    userId = UserHandle.USER_SYSTEM;
+                }
                 if (DEBUG_INSTALL) {
                     Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId);
                 }
@@ -18944,7 +18963,8 @@
 
     @GuardedBy("mPackages")
     private int getUidTargetSdkVersionLockedLPr(int uid) {
-        Object obj = mSettings.getSettingLPr(uid);
+        final int appId = UserHandle.getAppId(uid);
+        final Object obj = mSettings.getSettingLPr(appId);
         if (obj instanceof SharedUserSetting) {
             final SharedUserSetting sus = (SharedUserSetting) obj;
             int vers = Build.VERSION_CODES.CUR_DEVELOPMENT;
@@ -19135,7 +19155,7 @@
         // writer
         synchronized (mPackages) {
             PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null || pkg.applicationInfo.uid != callingUid) {
+            if (pkg == null || !isCallerSameApp(packageName, callingUid)) {
                 if (mContext.checkCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                         != PackageManager.PERMISSION_GRANTED) {
@@ -19808,6 +19828,14 @@
                         .setPackage(launcherComponent.getPackageName());
                 mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
             }
+            // TODO(b/122900055) Change/Remove this and replace with new permission role.
+            if (mAppPredictionServicePackage != null) {
+                Intent predictorIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+                        .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+                        .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+                        .setPackage(mAppPredictionServicePackage);
+                mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUid));
+            }
         }
     }
 
@@ -19960,6 +19988,20 @@
         return mContext.getString(R.string.config_defaultWellbeingPackage);
     }
 
+    private String getAppPredictionServicePackageName() {
+        String flattenedAppPredictionServiceComponentName =
+                mContext.getString(R.string.config_defaultAppPredictionService);
+        if (flattenedAppPredictionServiceComponentName == null) {
+            return null;
+        }
+        ComponentName appPredictionServiceComponentName =
+                ComponentName.unflattenFromString(flattenedAppPredictionServiceComponentName);
+        if (appPredictionServiceComponentName == null) {
+            return null;
+        }
+        return appPredictionServiceComponentName.getPackageName();
+    }
+
     @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {
@@ -23122,6 +23164,8 @@
                     return mWellbeingPackage;
                 case PackageManagerInternal.PACKAGE_DOCUMENTER:
                     return mDocumenterPackage;
+                case PackageManagerInternal.PACKAGE_CONFIGURATOR:
+                    return mConfiguratorPackage;
             }
             return null;
         }
@@ -23138,6 +23182,11 @@
         }
 
         @Override
+        public void setLocationExtraPackagesProvider(PackagesProvider provider) {
+            mDefaultPermissionPolicy.setLocationExtraPackagesProvider(provider);
+        }
+
+        @Override
         public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
             mDefaultPermissionPolicy.setVoiceInteractionPackagesProvider(provider);
         }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 95da209..b0f2326 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2790,13 +2790,13 @@
                 // dataPath   - path to package's data path
                 // seinfo     - seinfo label for the app (assigned at install time)
                 // gids       - supplementary gids this app launches with
+                // profileableFromShellFlag  - 0 or 1 if the package is profileable from shell.
                 //
                 // NOTE: We prefer not to expose all ApplicationInfo flags for now.
                 //
                 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
                 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
-                //   frameworks/base/libs/packagelistparser
-                //   system/core/run-as/run-as.c
+                //   system/core/libpackagelistparser
                 //
                 sb.setLength(0);
                 sb.append(ai.packageName);
@@ -2816,6 +2816,8 @@
                 } else {
                     sb.append("none");
                 }
+                sb.append(" ");
+                sb.append(ai.isProfileableByShell() ? "1" : "0");
                 sb.append("\n");
                 writer.append(sb);
             }
diff --git a/services/core/java/com/android/server/pm/dex/DexLogger.java b/services/core/java/com/android/server/pm/dex/DexLogger.java
index 68a755b..78fa82c 100644
--- a/services/core/java/com/android/server/pm/dex/DexLogger.java
+++ b/services/core/java/com/android/server/pm/dex/DexLogger.java
@@ -28,7 +28,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
@@ -53,21 +52,18 @@
 
     private final IPackageManager mPackageManager;
     private final PackageDynamicCodeLoading mPackageDynamicCodeLoading;
-    private final Object mInstallLock;
-    @GuardedBy("mInstallLock")
     private final Installer mInstaller;
 
-    public DexLogger(IPackageManager pms, Installer installer, Object installLock) {
-        this(pms, installer, installLock, new PackageDynamicCodeLoading());
+    public DexLogger(IPackageManager pms, Installer installer) {
+        this(pms, installer, new PackageDynamicCodeLoading());
     }
 
     @VisibleForTesting
-    DexLogger(IPackageManager pms, Installer installer, Object installLock,
+    DexLogger(IPackageManager pms, Installer installer,
             PackageDynamicCodeLoading packageDynamicCodeLoading) {
         mPackageManager = pms;
         mPackageDynamicCodeLoading = packageDynamicCodeLoading;
         mInstaller = installer;
-        mInstallLock = installLock;
     }
 
     public Set<String> getAllPackagesWithDynamicCodeLoading() {
@@ -131,14 +127,16 @@
             }
 
             byte[] hash = null;
-            synchronized (mInstallLock) {
-                try {
-                    hash = mInstaller.hashSecondaryDexFile(filePath, packageName, appInfo.uid,
-                            appInfo.volumeUuid, storageFlags);
-                } catch (InstallerException e) {
-                    Slog.e(TAG, "Got InstallerException when hashing file " + filePath
-                            + ": " + e.getMessage());
-                }
+            try {
+                // Note that we do not take the install lock here. Hashing should never interfere
+                // with app update/compilation/removal. We may get anomalous results if a file
+                // changes while we hash it, but that can happen anyway and is harmless for our
+                // purposes.
+                hash = mInstaller.hashSecondaryDexFile(filePath, packageName, appInfo.uid,
+                        appInfo.volumeUuid, storageFlags);
+            } catch (InstallerException e) {
+                Slog.e(TAG, "Got InstallerException when hashing file " + filePath
+                        + ": " + e.getMessage());
             }
 
             String fileName = new File(filePath).getName();
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index e57d9d7..b546836 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -129,7 +129,7 @@
         mPackageDexOptimizer = pdo;
         mInstaller = installer;
         mInstallLock = installLock;
-        mDexLogger = new DexLogger(pms, installer, installLock);
+        mDexLogger = new DexLogger(pms, installer);
     }
 
     public DexLogger getDexLogger() {
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 3a49412..17f8347 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -247,6 +247,10 @@
     public boolean isDocumenter() {
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0;
     }
+    public boolean isConfigurator() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR)
+            != 0;
+    }
 
     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
         if (!origPackageName.equals(sourcePackageName)) {
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 789664d..ceaf69d 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -225,6 +225,7 @@
     private final Handler mHandler;
 
     private PackagesProvider mLocationPackagesProvider;
+    private PackagesProvider mLocationExtraPackagesProvider;
     private PackagesProvider mVoiceInteractionPackagesProvider;
     private PackagesProvider mSmsAppPackagesProvider;
     private PackagesProvider mDialerAppPackagesProvider;
@@ -270,6 +271,13 @@
         }
     }
 
+    /** Sets the provider for loction extra packages. */
+    public void setLocationExtraPackagesProvider(PackagesProvider provider) {
+        synchronized (mLock) {
+            mLocationExtraPackagesProvider = provider;
+        }
+    }
+
     public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
         synchronized (mLock) {
             mVoiceInteractionPackagesProvider = provider;
@@ -403,6 +411,7 @@
         Log.i(TAG, "Granting permissions to default platform handlers for user " + userId);
 
         final PackagesProvider locationPackagesProvider;
+        final PackagesProvider locationExtraPackagesProvider;
         final PackagesProvider voiceInteractionPackagesProvider;
         final PackagesProvider smsAppPackagesProvider;
         final PackagesProvider dialerAppPackagesProvider;
@@ -412,6 +421,7 @@
 
         synchronized (mLock) {
             locationPackagesProvider = mLocationPackagesProvider;
+            locationExtraPackagesProvider = mLocationExtraPackagesProvider;
             voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
             smsAppPackagesProvider = mSmsAppPackagesProvider;
             dialerAppPackagesProvider = mDialerAppPackagesProvider;
@@ -424,6 +434,8 @@
                 ? voiceInteractionPackagesProvider.getPackages(userId) : null;
         String[] locationPackageNames = (locationPackagesProvider != null)
                 ? locationPackagesProvider.getPackages(userId) : null;
+        String[] locationExtraPackageNames = (locationExtraPackagesProvider != null)
+                ? locationExtraPackagesProvider.getPackages(userId) : null;
         String[] smsAppPackageNames = (smsAppPackagesProvider != null)
                 ? smsAppPackagesProvider.getPackages(userId) : null;
         String[] dialerAppPackageNames = (dialerAppPackagesProvider != null)
@@ -638,6 +650,12 @@
                         LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
             }
         }
+        if (locationExtraPackageNames != null) {
+            // Also grant location permission to location extra packages.
+            for (String packageName : locationExtraPackageNames) {
+                grantPermissionsToSystemPackage(packageName, userId, LOCATION_PERMISSIONS);
+            }
+        }
 
         // Music
         Intent musicIntent = new Intent(Intent.ACTION_VIEW)
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 93964cb..30b5e49 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1640,6 +1640,13 @@
                 // Special permissions for the system default text classifier.
                 allowed = true;
             }
+            if (!allowed && bp.isConfigurator()
+                    && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
+                    PackageManagerInternal.PACKAGE_CONFIGURATOR,
+                    UserHandle.USER_SYSTEM))) {
+                // Special permissions for the device configurator.
+                allowed = true;
+            }
             if (!allowed && bp.isWellbeing()
                     && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName(
                     PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM))) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2060aef..6b111a0 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -84,8 +84,10 @@
 import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
 
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
-import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
-import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs
+        .CAMERA_LENS_COVER_ABSENT;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs
+        .CAMERA_LENS_UNCOVERED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
 import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
 import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
@@ -478,6 +480,7 @@
     int mShortPressOnSleepBehavior;
     int mShortPressOnWindowBehavior;
     boolean mHasSoftInput = false;
+    boolean mHapticTextHandleEnabled;
     boolean mUseTvRouting;
     int mVeryLongPressTimeout;
     boolean mAllowStartActivityForLongPressOnPowerDuringSetup;
@@ -565,6 +568,10 @@
     private boolean mScreenshotChordPowerKeyTriggered;
     private long mScreenshotChordPowerKeyTime;
 
+    private static final long MOVING_DISPLAY_TO_TOP_DURATION_MILLIS = 10;
+    private volatile boolean mMovingDisplayToTopKeyTriggered;
+    private volatile long mMovingDisplayToTopKeyTime;
+
     // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up
     private int mRingerToggleChord = VOLUME_HUSH_OFF;
 
@@ -604,7 +611,7 @@
     private boolean mAodShowing;
 
     private boolean mPerDisplayFocusEnabled = false;
-    private int mTopFocusedDisplayId = INVALID_DISPLAY;
+    private volatile int mTopFocusedDisplayId = INVALID_DISPLAY;
 
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
@@ -632,6 +639,7 @@
     private static final int MSG_POWER_VERY_LONG_PRESS = 25;
     private static final int MSG_NOTIFY_USER_ACTIVITY = 26;
     private static final int MSG_RINGER_TOGGLE_CHORD = 27;
+    private static final int MSG_MOVE_DISPLAY_TO_TOP = 28;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -727,6 +735,10 @@
                 case MSG_RINGER_TOGGLE_CHORD:
                     handleRingerChordGesture();
                     break;
+                case MSG_MOVE_DISPLAY_TO_TOP:
+                    mWindowManagerFuncs.moveDisplayToTop(msg.arg1);
+                    mMovingDisplayToTopKeyTriggered = false;
+                    break;
             }
         }
     }
@@ -808,6 +820,13 @@
         }
     };
 
+    private Runnable mPossibleVeryLongPressReboot = new Runnable() {
+        @Override
+        public void run() {
+            mActivityManagerInternal.prepareForPossibleShutdown();
+        }
+    };
+
     private void handleRingerChordGesture() {
         if (mRingerToggleChord == VOLUME_HUSH_OFF) {
             return;
@@ -953,6 +972,8 @@
         // Inform the StatusBar; but do not allow it to consume the event.
         sendSystemKeyToStatusBarAsync(event.getKeyCode());
 
+        schedulePossibleVeryLongPressReboot();
+
         // If the power key has still not yet been handled, then detect short
         // press, long press, or multi press and decide what to do.
         mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
@@ -1056,6 +1077,7 @@
         if (hasVeryLongPressOnPowerBehavior()) {
             mHandler.removeMessages(MSG_POWER_VERY_LONG_PRESS);
         }
+        cancelPossibleVeryLongPressReboot();
     }
 
     private void cancelPendingBackKeyAction() {
@@ -1815,6 +1837,9 @@
         mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup);
 
+        mHapticTextHandleEnabled = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableHapticTextHandle);
+
         mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
 
         mHandleVolumeKeysInWM = mContext.getResources().getBoolean(
@@ -2558,12 +2583,25 @@
         final int eventDisplayId = event.getDisplayId();
         if (result == 0 && !mPerDisplayFocusEnabled
                 && eventDisplayId != INVALID_DISPLAY && eventDisplayId != mTopFocusedDisplayId) {
-            // Someone tries to send a key event to a display which doesn't have a focused window.
-            // We drop the event here, or it will cause ANR.
-            // TODO (b/121057974): The user may be confused about why the key doesn't work, so we
-            // may need to deal with this problem.
-            Slog.i(TAG, "Dropping this event targeting display #" + eventDisplayId
-                    + " because the focus is on display #" + mTopFocusedDisplayId);
+            // An event is targeting a non-focused display. Try to move the display to top so that
+            // it can become the focused display to interact with the user.
+            final long eventDownTime = event.getDownTime();
+            if (mMovingDisplayToTopKeyTime < eventDownTime) {
+                // We have not handled this event yet. Move the display to top, and then tell
+                // dispatcher to try again later.
+                mMovingDisplayToTopKeyTime = eventDownTime;
+                mMovingDisplayToTopKeyTriggered = true;
+                mHandler.sendMessage(
+                        mHandler.obtainMessage(MSG_MOVE_DISPLAY_TO_TOP, eventDisplayId, 0));
+                return MOVING_DISPLAY_TO_TOP_DURATION_MILLIS;
+            } else if (mMovingDisplayToTopKeyTriggered) {
+                // The message has not been handled yet. Tell dispatcher to try again later.
+                return MOVING_DISPLAY_TO_TOP_DURATION_MILLIS;
+            }
+            // The target display is still not the top focused display. Drop the event because the
+            // display may not contain any window which can receive keys.
+            Slog.w(TAG, "Dropping key targeting non-focused display #" + eventDisplayId
+                    + " keyCode=" + KeyEvent.keyCodeToString(event.getKeyCode()));
             return -1;
         }
         return result;
@@ -4901,6 +4939,15 @@
         }
     }
 
+    private void schedulePossibleVeryLongPressReboot() {
+        mHandler.removeCallbacks(mPossibleVeryLongPressReboot);
+        mHandler.postDelayed(mPossibleVeryLongPressReboot, mVeryLongPressTimeout);
+    }
+
+    private void cancelPossibleVeryLongPressReboot() {
+        mHandler.removeCallbacks(mPossibleVeryLongPressReboot);
+    }
+
     // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
     private void updateScreenOffSleepToken(boolean acquire) {
         if (acquire) {
@@ -5158,8 +5205,11 @@
             case HapticFeedbackConstants.CLOCK_TICK:
             case HapticFeedbackConstants.CONTEXT_CLICK:
                 return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
-            case HapticFeedbackConstants.KEYBOARD_RELEASE:
             case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
+                if (!mHapticTextHandleEnabled) {
+                    return null;
+                }
+            case HapticFeedbackConstants.KEYBOARD_RELEASE:
             case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
             case HapticFeedbackConstants.ENTRY_BUMP:
             case HapticFeedbackConstants.DRAG_CROSSING:
@@ -5324,11 +5374,13 @@
                 pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
         pw.print(prefix);
                 pw.print("mHasSoftInput="); pw.print(mHasSoftInput);
-                pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed);
+                pw.print(" mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled);
         pw.print(prefix);
-                pw.print("mIncallPowerBehavior=");
-                pw.print(incallPowerBehaviorToString(mIncallPowerBehavior));
-                pw.print(" mIncallBackBehavior=");
+                pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed);
+                pw.print(" mIncallPowerBehavior=");
+                pw.println(incallPowerBehaviorToString(mIncallPowerBehavior));
+        pw.print(prefix);
+                pw.print("mIncallBackBehavior=");
                 pw.print(incallBackBehaviorToString(mIncallBackBehavior));
                 pw.print(" mEndcallBehavior=");
                 pw.println(endcallBehaviorToString(mEndcallBehavior));
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 3da325c..c37254b 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -634,6 +634,12 @@
          * Notifies window manager that user is switched.
          */
         void onUserSwitched();
+
+        /**
+         * Hint to window manager that the user is interacting with a display that should be treated
+         * as the top display.
+         */
+        void moveDisplayToTop(int displayId);
     }
 
     /**
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 45c975b..055c941 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -62,6 +62,8 @@
                         mContext.getContentResolver(),
                         Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
 
+                // TODO: STOPSHIP: Remove the following code once we remove default_sms_application
+                // and use the new config_defaultRoleHolders.
                 if (result == null) {
                     Collection<SmsApplication.SmsApplicationData> applications =
                             SmsApplication.getApplicationCollectionAsUser(mContext, userId);
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c0ec367..5516b23 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -229,9 +229,12 @@
         // Any role for which we have a record are already migrated
         RoleUserState userState = getOrCreateUserState(userId);
         if (!userState.isRoleAvailable(role)) {
-            userState.addRoleName(role);
             List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
+            if (roleHolders.isEmpty()) {
+                return;
+            }
             Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
+            userState.addRoleName(role);
             int size = roleHolders.size();
             for (int i = 0; i < size; i++) {
                 userState.addRoleHolder(role, roleHolders.get(i));
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 1f638c7..65d66f4 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -278,12 +278,12 @@
         }
 
         // Since positionChildAt() is called during the creation process of pinned stacks,
-        // ActivityStack#getWindowContainerController() can be null. In this special case,
+        // ActivityStack#getStack() can be null. In this special case,
         // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
         // we don't have to call WindowContainerController#positionChildAt() here.
-        if (stack.getWindowContainerController() != null && mDisplayContent != null) {
+        if (stack.getTaskStack() != null && mDisplayContent != null) {
             mDisplayContent.positionStackAt(insertPosition,
-                    stack.getWindowContainerController().mContainer, includingParents);
+                    stack.getTaskStack(), includingParents);
         }
         if (!wasContained) {
             stack.setParent(this);
@@ -450,13 +450,12 @@
     @VisibleForTesting
     <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
             int stackId, boolean onTop) {
-        if (windowingMode == WINDOWING_MODE_PINNED) {
-            return (T) new PinnedActivityStack(this, stackId,
-                    mRootActivityContainer.mStackSupervisor, onTop);
+        if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
+            throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
+                    + "activity type.");
         }
         return (T) new ActivityStack(this, stackId,
-                mRootActivityContainer.mStackSupervisor, windowingMode, activityType,
-                onTop);
+                mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
     }
 
     /**
@@ -626,6 +625,10 @@
             return;
         }
 
+        // Collect the stacks that are necessary to be removed instead of performing the removal
+        // by looping mStacks, so that we don't miss any stacks after the stack size changed or
+        // stacks reordered.
+        final ArrayList<ActivityStack> stacks = new ArrayList<>();
         for (int j = windowingModes.length - 1 ; j >= 0; --j) {
             final int windowingMode = windowingModes[j];
             for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -636,9 +639,13 @@
                 if (stack.getWindowingMode() != windowingMode) {
                     continue;
                 }
-                mRootActivityContainer.mStackSupervisor.removeStack(stack);
+                stacks.add(stack);
             }
         }
+
+        for (int i = stacks.size() - 1; i >= 0; --i) {
+            mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
+        }
     }
 
     void removeStacksWithActivityTypes(int... activityTypes) {
@@ -646,15 +653,23 @@
             return;
         }
 
+        // Collect the stacks that are necessary to be removed instead of performing the removal
+        // by looping mStacks, so that we don't miss any stacks after the stack size changed or
+        // stacks reordered.
+        final ArrayList<ActivityStack> stacks = new ArrayList<>();
         for (int j = activityTypes.length - 1 ; j >= 0; --j) {
             final int activityType = activityTypes[j];
             for (int i = mStacks.size() - 1; i >= 0; --i) {
                 final ActivityStack stack = mStacks.get(i);
                 if (stack.getActivityType() == activityType) {
-                    mRootActivityContainer.mStackSupervisor.removeStack(stack);
+                    stacks.add(stack);
                 }
             }
         }
+
+        for (int i = stacks.size() - 1; i >= 0; --i) {
+            mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
+        }
     }
 
     void onStackWindowingModeChanged(ActivityStack stack) {
@@ -1019,8 +1034,8 @@
         return mSplitScreenPrimaryStack != null;
     }
 
-    PinnedActivityStack getPinnedStack() {
-        return (PinnedActivityStack) mPinnedStack;
+    ActivityStack getPinnedStack() {
+        return mPinnedStack;
     }
 
     boolean hasPinnedStack() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9f8af50..b8634d8 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2508,6 +2508,13 @@
         final IBinder binder =
                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
         mAppWindowToken.setOrientation(requestedOrientation, binder, this);
+
+        // Push the new configuration to the requested app in case where it's not pushed, e.g. when
+        // the request is handled at task level with letterbox.
+        if (!getMergedOverrideConfiguration().equals(
+                mLastReportedConfiguration.getMergedConfiguration())) {
+            ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
+        }
     }
 
     int getOrientation() {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 4d7de905..891c3da 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -114,6 +114,7 @@
 import android.app.ActivityOptions;
 import android.app.AppGlobals;
 import android.app.IActivityController;
+import android.app.RemoteAction;
 import android.app.ResultInfo;
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
@@ -173,8 +174,7 @@
 /**
  * State and management of a single stack of activities.
  */
-class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
-        implements StackWindowListener {
+class ActivityStack extends ConfigurationContainer {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
     private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -297,8 +297,7 @@
     static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
 
     final ActivityTaskManagerService mService;
-    private final WindowManagerService mWindowManager;
-    T mWindowContainerController;
+    final WindowManagerService mWindowManager;
 
     /**
      * The back history of all previous (and possibly still
@@ -397,6 +396,9 @@
     static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5;
     static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6;
 
+    // TODO: remove after unification.
+    TaskStack mTaskStack;
+
     private static class ScheduleDestroyArgs {
         final WindowProcessController mOwner;
         final String mReason;
@@ -495,21 +497,30 @@
         // stacks on a wrong display.
         mDisplayId = display.mDisplayId;
         setActivityType(activityType);
-        mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
-                mTmpRect2);
+        createTaskStack(display.mDisplayId, onTop, mTmpRect2);
         setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
                 true /* creating */);
         display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
     }
 
-    T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
-        return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds,
-                mRootActivityContainer.mWindowManager);
+    void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
+        final DisplayContent dc = mWindowManager.mRoot.getDisplayContent(displayId);
+        if (dc == null) {
+            throw new IllegalArgumentException("Trying to add stackId=" + mStackId
+                    + " to unknown displayId=" + displayId);
+        }
+        mTaskStack = new TaskStack(mWindowManager, mStackId, this);
+        dc.setStackOnDisplay(mStackId, onTop, mTaskStack);
+        if (mTaskStack.matchParentBounds()) {
+            outBounds.setEmpty();
+        } else {
+            mTaskStack.getRawBounds(outBounds);
+        }
     }
 
-    T getWindowContainerController() {
-        return mWindowContainerController;
+    TaskStack getTaskStack() {
+        return mTaskStack;
     }
 
     /**
@@ -553,6 +564,9 @@
         if (display == null) {
             return;
         }
+        if (getTaskStack() == null) {
+            return;
+        }
 
         // Update bounds if applicable
         boolean hasNewOverrideBounds = false;
@@ -560,8 +574,7 @@
         if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
             // Pinned calculation already includes rotation
             mTmpRect2.set(mTmpRect);
-            hasNewOverrideBounds = getWindowContainerController().mContainer
-                            .calculatePinnedBoundsForConfigChange(mTmpRect2);
+            hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(mTmpRect2);
         } else {
             final int newRotation = getWindowConfiguration().getRotation();
             if (!matchParentBounds()) {
@@ -588,7 +601,7 @@
                             || getRequestedOverrideWindowingMode()
                             == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
                         mTmpRect2.set(mTmpRect);
-                        getWindowContainerController().mContainer
+                        getTaskStack()
                                 .calculateDockedBoundsForConfigChange(newParentConfig, mTmpRect2);
                         hasNewOverrideBounds = true;
                     }
@@ -786,7 +799,11 @@
 
             mTmpRect2.setEmpty();
             if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
-                mWindowContainerController.getRawBounds(mTmpRect2);
+                if (mTaskStack.matchParentBounds()) {
+                    mTmpRect2.setEmpty();
+                } else {
+                    mTaskStack.getRawBounds(mTmpRect2);
+                }
             }
 
             if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
@@ -843,7 +860,12 @@
         // Reparent the window container before we try to update the position when adding it to
         // the new display below
         mTmpRect2.setEmpty();
-        mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
+        if (mTaskStack == null) {
+            // TODO: Remove after unification.
+            Log.w(TAG, "Task stack is not valid when reparenting.");
+        } else {
+            mTaskStack.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
+        }
         setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2);
         activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
         if (!displayRemoved) {
@@ -876,8 +898,10 @@
     /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
     void remove() {
         removeFromDisplay();
-        mWindowContainerController.removeContainer();
-        mWindowContainerController = null;
+        if (mTaskStack != null) {
+            mTaskStack.removeIfPossible();
+            mTaskStack = null;
+        }
         onParentChanged();
     }
 
@@ -890,26 +914,35 @@
      */
     void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds,
             Rect outStackBounds, Rect outTempTaskBounds) {
-        mWindowContainerController.getStackDockedModeBounds(getParent().getConfiguration(),
-                dockedBounds, currentTempTaskBounds,
-                outStackBounds, outTempTaskBounds);
+        if (mTaskStack != null) {
+            mTaskStack.getStackDockedModeBoundsLocked(getParent().getConfiguration(), dockedBounds,
+                    currentTempTaskBounds, outStackBounds, outTempTaskBounds);
+        } else {
+            outStackBounds.setEmpty();
+            outTempTaskBounds.setEmpty();
+        }
     }
 
     void prepareFreezingTaskBounds() {
-        mWindowContainerController.prepareFreezingTaskBounds();
+        if (mTaskStack != null) {
+            // TODO: This cannot be false after unification.
+            mTaskStack.prepareFreezingTaskBounds();
+        }
     }
 
     void getWindowContainerBounds(Rect outBounds) {
-        if (mWindowContainerController != null) {
-            mWindowContainerController.getBounds(outBounds);
+        if (mTaskStack != null) {
+            mTaskStack.getBounds(outBounds);
             return;
         }
         outBounds.setEmpty();
     }
 
     void positionChildWindowContainerAtTop(TaskRecord child) {
-        mWindowContainerController.positionChildAtTop(child.getTask(),
-                true /* includingParents */);
+        if (mTaskStack != null) {
+            // TODO: Remove after unification. This cannot be false after that.
+            mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */);
+        }
     }
 
     void positionChildWindowContainerAtBottom(TaskRecord child) {
@@ -918,14 +951,27 @@
         // task to bottom, the next focusable stack on the same display should be focused.
         final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack(
                 child.getStack(), true /* ignoreCurrent */);
-        mWindowContainerController.positionChildAtBottom(child.getTask(),
-                nextFocusableStack == null /* includingParents */);
+        if (mTaskStack != null) {
+            // TODO: Remove after unification. This cannot be false after that.
+            mTaskStack.positionChildAtBottom(child.getTask(),
+                    nextFocusableStack == null /* includingParents */);
+        }
     }
 
     /**
      * Returns whether to defer the scheduling of the multi-window mode.
      */
     boolean deferScheduleMultiWindowModeChanged() {
+        if (inPinnedWindowingMode()) {
+            // For the pinned stack, the deferring of the multi-window mode changed is tied to the
+            // transition animation into picture-in-picture, and is called once the animation
+            // completes, or is interrupted in a way that would leave the stack in a non-fullscreen
+            // state.
+            // @see BoundsAnimationController
+            // @see BoundsAnimationControllerTests
+            if (getTaskStack() == null) return false;
+            return getTaskStack().deferScheduleMultiWindowModeChanged();
+        }
         return false;
     }
 
@@ -2994,7 +3040,10 @@
         position = getAdjustedPositionForTask(task, position, null /* starting */);
         mTaskHistory.remove(task);
         mTaskHistory.add(position, task);
-        mWindowContainerController.positionChildAt(task.getTask(), position);
+        if (mTaskStack != null) {
+            // TODO: this could not be false after unification.
+            mTaskStack.positionChildAt(task.getTask(), position);
+        }
         updateTaskMovement(task, true);
     }
 
@@ -4909,8 +4958,7 @@
     }
 
     // TODO: Figure-out a way to consolidate with resize() method below.
-    @Override
-    public void requestResize(Rect bounds) {
+    void requestResize(Rect bounds) {
         mService.resizeStack(mStackId, bounds,
                 true /* allowResizeInDockedMode */, false /* preserveWindows */,
                 false /* animate */, -1 /* animationDuration */);
@@ -4948,7 +4996,8 @@
     }
 
     void onPipAnimationEndResize() {
-        mWindowContainerController.onPipAnimationEndResize();
+        if (mTaskStack == null) return;
+        mTaskStack.onPipAnimationEndResize();
     }
 
 
@@ -5494,6 +5543,65 @@
         }
     }
 
+
+    Rect getDefaultPictureInPictureBounds(float aspectRatio) {
+        if (getTaskStack() == null) return null;
+        return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */);
+    }
+
+    void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
+            boolean fromFullscreen) {
+        if (!inPinnedWindowingMode()) return;
+        if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
+            mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
+        } else {
+            if (getTaskStack() == null) return;
+            getTaskStack().animateResizePinnedStack(toBounds, sourceHintBounds,
+                    animationDuration, fromFullscreen);
+        }
+    }
+
+    private boolean skipResizeAnimation(boolean toFullscreen) {
+        if (!toFullscreen) {
+            return false;
+        }
+        final Configuration parentConfig = getParent().getConfiguration();
+        final ActivityRecord top = topRunningNonOverlayTaskActivity();
+        return top != null && !top.isConfigurationCompatible(parentConfig);
+    }
+
+    void setPictureInPictureAspectRatio(float aspectRatio) {
+        if (getTaskStack() == null) return;
+        getTaskStack().setPictureInPictureAspectRatio(aspectRatio);
+    }
+
+    void setPictureInPictureActions(List<RemoteAction> actions) {
+        if (getTaskStack() == null) return;
+        getTaskStack().setPictureInPictureActions(actions);
+    }
+
+    boolean isAnimatingBoundsToFullscreen() {
+        if (getTaskStack() == null) return false;
+        return getTaskStack().isAnimatingBoundsToFullscreen();
+    }
+
+    public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
+            boolean forceUpdate) {
+        // It is guaranteed that the activities requiring the update will be in the pinned stack at
+        // this point (either reparented before the animation into PiP, or before reparenting after
+        // the animation out of PiP)
+        synchronized (mService.mGlobalLock) {
+            if (!isAttached()) {
+                return;
+            }
+            ArrayList<TaskRecord> tasks = getAllTasks();
+            for (int i = 0; i < tasks.size(); i++) {
+                mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
+                        forceUpdate);
+            }
+        }
+    }
+
     public int getStackId() {
         return mStackId;
     }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a50ae84..3a288ca 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1674,8 +1674,8 @@
     }
 
     void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
-        // TODO(multi-display): Pinned stack display should be passed in.
-        final PinnedActivityStack stack =
+        // TODO(multi-display): The display containing the stack should be passed in.
+        final ActivityStack stack =
                 mRootActivityContainer.getDefaultDisplay().getPinnedStack();
         if (stack == null) {
             Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
@@ -1686,7 +1686,7 @@
         // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be
         // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting
         // for the AMS lock to be freed. So check and make sure these bounds are still good.
-        final PinnedStackWindowController stackController = stack.getWindowContainerController();
+        final TaskStack stackController = stack.getTaskStack();
         if (stackController.pinnedStackResizeDisallowed()) {
             return;
         }
@@ -1730,15 +1730,14 @@
              * invisible as well and added to the stopping list.  After which we process the
              * stopping list by handling the idle.
              */
-            final PinnedActivityStack pinnedStack = (PinnedActivityStack) stack;
-            pinnedStack.mForceHidden = true;
-            pinnedStack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
-            pinnedStack.mForceHidden = false;
+            stack.mForceHidden = true;
+            stack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+            stack.mForceHidden = false;
             activityIdleInternalLocked(null, false /* fromTimeout */,
                     true /* processPausingActivites */, null /* configuration */);
 
             // Move all the tasks to the bottom of the fullscreen stack
-            moveTasksToFullscreenStackLocked(pinnedStack, !ON_TOP);
+            moveTasksToFullscreenStackLocked(stack, !ON_TOP);
         } else {
             for (int i = tasks.size() - 1; i >= 0; i--) {
                 removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */,
@@ -2642,6 +2641,9 @@
                 try {
                     mService.moveTaskToFrontLocked(task.taskId, 0, options,
                             true /* fromRecents */);
+                    // Apply options to prevent pendingOptions be taken by client to make sure
+                    // the override pending app transition will be applied immediately.
+                    targetActivity.applyOptionsLocked();
                 } finally {
                     mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
                             targetActivity);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e82e748..6a495d4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -82,13 +82,10 @@
 import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC;
 import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY;
 import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto
-        .PREVIOUS_PROC_VISIBLE_TIME_MS;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS;
 import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
-        .MODE;
-import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
-        .PACKAGE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE;
+import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -210,6 +207,7 @@
 import android.provider.Settings;
 import android.service.voice.IVoiceInteractionSession;
 import android.service.voice.VoiceInteractionManagerInternal;
+import android.sysprop.DisplayProperties;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.text.format.Time;
@@ -245,7 +243,6 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.server.appop.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -261,6 +258,7 @@
 import com.android.server.am.PendingIntentController;
 import com.android.server.am.PendingIntentRecord;
 import com.android.server.am.UserState;
+import com.android.server.appop.AppOpsService;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.pm.UserManagerService;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -694,7 +692,7 @@
         final boolean isPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
 
         // Transfer any global setting for forcing RTL layout, into a System Property
-        SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
+        DisplayProperties.debug_force_rtl(forceRtl);
 
         final Configuration configuration = new Configuration();
         Settings.System.getConfiguration(resolver, configuration);
@@ -2407,7 +2405,7 @@
         try {
             synchronized (mGlobalLock) {
                 if (animate) {
-                    final PinnedActivityStack stack = mRootActivityContainer.getStack(stackId);
+                    final ActivityStack stack = mRootActivityContainer.getStack(stackId);
                     if (stack == null) {
                         Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
                         return;
@@ -3712,7 +3710,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                final PinnedActivityStack stack =
+                final ActivityStack stack =
                         mRootActivityContainer.getDefaultDisplay().getPinnedStack();
                 if (stack == null) {
                     Slog.w(TAG, "dismissPip: pinned stack not found.");
@@ -3834,9 +3832,8 @@
 
         // If we are animating to fullscreen then we have already dispatched the PIP mode
         // changed, so we should reflect that check here as well.
-        final PinnedActivityStack stack = r.getActivityStack();
-        final PinnedStackWindowController windowController = stack.getWindowContainerController();
-        return !windowController.mContainer.isAnimatingBoundsToFullscreen();
+        final TaskStack taskStack = r.getActivityStack().getTaskStack();
+        return !taskStack.isAnimatingBoundsToFullscreen();
     }
 
     @Override
@@ -3870,7 +3867,7 @@
                                 r.pictureInPictureArgs.getSourceRectHint());
                         mRootActivityContainer.moveActivityToPinnedStack(
                                 r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
-                        final PinnedActivityStack stack = r.getActivityStack();
+                        final ActivityStack stack = r.getActivityStack();
                         stack.setPictureInPictureAspectRatio(aspectRatio);
                         stack.setPictureInPictureActions(actions);
                         MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
@@ -3914,7 +3911,7 @@
                     // If the activity is already in picture-in-picture, update the pinned stack now
                     // if it is not already expanding to fullscreen. Otherwise, the arguments will
                     // be used the next time the activity enters PiP
-                    final PinnedActivityStack stack = r.getActivityStack();
+                    final ActivityStack stack = r.getActivityStack();
                     if (!stack.isAnimatingBoundsToFullscreen()) {
                         stack.setPictureInPictureAspectRatio(
                                 r.pictureInPictureArgs.getAspectRatio());
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 740d472..6527ca0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -328,14 +328,6 @@
     private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
 
     /**
-     * Flag indicating that the application is receiving an orientation that has different metrics
-     * than it expected. E.g. Portrait instead of Landscape.
-     *
-     * @see #updateRotationUnchecked()
-     */
-    private boolean mAltOrientation = false;
-
-    /**
      * Orientation forced by some window. If there is no visible window that specifies orientation
      * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}.
      *
@@ -1085,10 +1077,6 @@
         return mLastOrientation;
     }
 
-    boolean getAltOrientation() {
-        return mAltOrientation;
-    }
-
     int getLastWindowForcedOrientation() {
         return mLastWindowForcedOrientation;
     }
@@ -1130,15 +1118,9 @@
     boolean rotationNeedsUpdate() {
         final int lastOrientation = getLastOrientation();
         final int oldRotation = getRotation();
-        final boolean oldAltOrientation = getAltOrientation();
 
         final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
-        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
-                lastOrientation, rotation);
-        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
-            return false;
-        }
-        return true;
+        return oldRotation != rotation;
     }
 
     /**
@@ -1160,12 +1142,14 @@
     @Override
     boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
             ConfigurationContainer requestingContainer) {
+        final int previousRotation = mRotation;
         final Configuration config = updateOrientationFromAppTokens(
                 getRequestedOverrideConfiguration(), freezeDisplayToken, false);
-        // If display rotation class tells us that it doesn't consider app requested orientation,
-        // this display won't rotate just because of an app changes its requested orientation. Thus
-        // it indicates that this display chooses not to handle this request.
-        final boolean handled = getDisplayRotation().respectAppRequestedOrientation();
+        // This event is considered handled iff a configuration propagation is triggered, because
+        // that's the only place lower level containers check if they need to do something to this
+        // request. The only guaranteed signal is that the display is rotated to a different
+        // orientation (i.e. rotating 180 degrees doesn't count).
+        final boolean handled = (mRotation - previousRotation) % 2 != 0;
         if (config == null) {
             return handled;
         }
@@ -1334,7 +1318,6 @@
 
         final int oldRotation = mRotation;
         final int lastOrientation = mLastOrientation;
-        final boolean oldAltOrientation = mAltOrientation;
         final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation);
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id="
                 + mDisplayId + " based on lastOrientation=" + lastOrientation
@@ -1366,35 +1349,26 @@
         }
         final boolean rotateSeamlessly = mayRotateSeamlessly;
 
-        // TODO: Implement forced rotation changes.
-        //       Set mAltOrientation to indicate that the application is receiving
-        //       an orientation that has different metrics than it expected.
-        //       eg. Portrait instead of Landscape.
-
-        final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics(
-                lastOrientation, rotation);
-
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
                 + " selected orientation " + lastOrientation
                 + ", got rotation " + rotation + " which has "
-                + (altOrientation ? "incompatible" : "compatible") + " metrics");
+                + " metrics");
 
-        if (oldRotation == rotation && oldAltOrientation == altOrientation) {
+        if (oldRotation == rotation) {
             // No change.
             return false;
         }
 
         if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
                 + " rotation changed to " + rotation
-                + (altOrientation ? " (alt)" : "") + " from " + oldRotation
-                + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation);
+                + " from " + oldRotation
+                + ", lastOrientation=" + lastOrientation);
 
         if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
             mWaitingForConfig = true;
         }
 
         mRotation = rotation;
-        mAltOrientation = altOrientation;
 
         mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
         mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
@@ -1536,26 +1510,8 @@
     private DisplayInfo updateDisplayAndOrientation(int uiMode) {
         // Use the effective "visual" dimensions based on current rotation
         final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
-        final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
-        final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
-        int dw = realdw;
-        int dh = realdh;
-
-        if (mAltOrientation) {
-            if (realdw > realdh) {
-                // Turn landscape into portrait.
-                int maxw = (int)(realdh/1.3f);
-                if (maxw < realdw) {
-                    dw = maxw;
-                }
-            } else {
-                // Turn portrait into landscape.
-                int maxh = (int)(realdw/1.3f);
-                if (maxh < realdh) {
-                    dh = maxh;
-                }
-            }
-        }
+        final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+        final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
 
         // Update application display metrics.
         final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation);
@@ -2307,13 +2263,12 @@
         out.set(mDisplayFrames.mStable);
     }
 
-    TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) {
-        if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
-                + mDisplayId);
+    void setStackOnDisplay(int stackId, boolean onTop, TaskStack stack) {
+        if (DEBUG_STACK) {
+            Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId);
+        }
 
-        final TaskStack stack = new TaskStack(mWmService, stackId, controller);
         mTaskStackContainers.addStackToDisplay(stack, onTop);
-        return stack;
     }
 
     void moveStackToDisplay(TaskStack stack, boolean onTop) {
@@ -4015,7 +3970,6 @@
 
         /**
          * Adds the stack to this container.
-         * @see DisplayContent#createStack(int, boolean, StackWindowController)
          */
         void addStackToDisplay(TaskStack stack, boolean onTop) {
             addStackReferenceIfNeeded(stack);
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index bcc7be4..bc165dc 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -329,15 +329,6 @@
         return mFixedToUserRotation;
     }
 
-    /**
-     * Returns {@code true} if this display rotation takes app requested orientation into
-     * consideration; {@code false} otherwise. For the time being the only case where this is {@code
-     * false} is when {@link #isFixedToUserRotation()} is {@code true}.
-     */
-    boolean respectAppRequestedOrientation() {
-        return !mFixedToUserRotation;
-    }
-
     public int getLandscapeRotation() {
         return mLandscapeRotation;
     }
@@ -685,36 +676,6 @@
         return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
     }
 
-    /**
-     * Given an orientation constant and a rotation, returns true if the rotation
-     * has compatible metrics to the requested orientation.  For example, if
-     * the application requested landscape and got seascape, then the rotation
-     * has compatible metrics; if the application requested portrait and got landscape,
-     * then the rotation has incompatible metrics; if the application did not specify
-     * a preference, then anything goes.
-     *
-     * @param orientation An orientation constant, such as
-     * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}.
-     * @param rotation The rotation to check.
-     * @return True if the rotation is compatible with the requested orientation.
-     */
-    boolean rotationHasCompatibleMetrics(int orientation, int rotation) {
-        switch (orientation) {
-            case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
-                return isAnyPortrait(rotation);
-
-            case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
-                return isLandscapeOrSeascape(rotation);
-
-            default:
-                return true;
-        }
-    }
-
     private boolean isValidRotationChoice(final int preferredRotation) {
         // Determine if the given app orientation is compatible with the provided rotation choice.
         switch (mCurrentAppOrientation) {
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 5f56fe5..177f244 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -462,22 +462,19 @@
             mOccluded = false;
             mDismissingKeyguardActivity = null;
 
-            // Only the top activity of the focused stack on each display may control it's
-            // occluded state.
-            final ActivityStack focusedStack = display.getFocusedStack();
-            if (focusedStack != null) {
-                final ActivityRecord topDismissing =
-                        focusedStack.getTopDismissingKeyguardActivity();
-                mOccluded = focusedStack.topActivityOccludesKeyguard() || (topDismissing != null
-                                && focusedStack.topRunningActivityLocked() == topDismissing
-                                && controller.canShowWhileOccluded(
+            final ActivityStack stack = getStackForControllingOccluding(display);
+            if (stack != null) {
+                final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity();
+                mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null
+                        && stack.topRunningActivityLocked() == topDismissing
+                        && controller.canShowWhileOccluded(
                                 true /* dismissKeyguard */,
                                 false /* showWhenLocked */));
-                if (focusedStack.getTopDismissingKeyguardActivity() != null) {
-                    mDismissingKeyguardActivity = focusedStack.getTopDismissingKeyguardActivity();
+                if (stack.getTopDismissingKeyguardActivity() != null) {
+                    mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
                 }
-                mOccluded |= controller.mWindowManager.isShowingDream();
             }
+            mOccluded |= controller.mWindowManager.isShowingDream();
 
             // TODO(b/113840485): Handle app transition for individual display, and apply occluded
             // state change to secondary displays.
@@ -492,6 +489,23 @@
             }
         }
 
+        /**
+         * Gets the stack used to check the occluded state.
+         * <p>
+         * Only the top non-pinned activity of the focusable stack on each display can control its
+         * occlusion state.
+         */
+        private ActivityStack getStackForControllingOccluding(ActivityDisplay display) {
+            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+                final ActivityStack stack = display.getChildAt(stackNdx);
+                if (stack != null && stack.isFocusableAndVisible()
+                        && !stack.inPinnedWindowingMode()) {
+                    return stack;
+                }
+            }
+            return null;
+        }
+
         void dumpStatus(PrintWriter pw, String prefix) {
             final StringBuilder sb = new StringBuilder();
             sb.append(prefix);
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 3062d34..86dc66d 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -221,7 +221,7 @@
     }
 
     private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) {
-        final ActivityStack<?> stack = task.getStack();
+        final ActivityStack stack = task.getStack();
         final int displayId = stack.mDisplayId;
         final ActivityDisplay display =
                 mSupervisor.mRootActivityContainer.getActivityDisplay(displayId);
diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java
deleted file mode 100644
index 2a05af4..0000000
--- a/services/core/java/com/android/server/wm/PinnedActivityStack.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-
-import android.app.RemoteAction;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * State and management of the pinned stack of activities.
- */
-class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
-        implements PinnedStackWindowListener {
-
-    PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
-            boolean onTop) {
-        super(display, stackId, supervisor, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, onTop);
-    }
-
-    @Override
-    PinnedStackWindowController createStackWindowController(int displayId, boolean onTop,
-            Rect outBounds) {
-        return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds,
-                mRootActivityContainer.mWindowManager);
-    }
-
-    Rect getDefaultPictureInPictureBounds(float aspectRatio) {
-        return getWindowContainerController().getPictureInPictureBounds(aspectRatio,
-                null /* currentStackBounds */);
-    }
-
-    void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
-            boolean fromFullscreen) {
-        if (skipResizeAnimation(toBounds == null /* toFullscreen */)) {
-            mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
-        } else {
-            getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
-                    animationDuration, fromFullscreen);
-        }
-    }
-
-    private boolean skipResizeAnimation(boolean toFullscreen) {
-        if (!toFullscreen) {
-            return false;
-        }
-        final Configuration parentConfig = getParent().getConfiguration();
-        final ActivityRecord top = topRunningNonOverlayTaskActivity();
-        return top != null && !top.isConfigurationCompatible(parentConfig);
-    }
-
-    void setPictureInPictureAspectRatio(float aspectRatio) {
-        getWindowContainerController().setPictureInPictureAspectRatio(aspectRatio);
-    }
-
-    void setPictureInPictureActions(List<RemoteAction> actions) {
-        getWindowContainerController().setPictureInPictureActions(actions);
-    }
-
-    boolean isAnimatingBoundsToFullscreen() {
-        return getWindowContainerController().mContainer.isAnimatingBoundsToFullscreen();
-    }
-
-    /**
-     * Returns whether to defer the scheduling of the multi-window mode.
-     */
-    boolean deferScheduleMultiWindowModeChanged() {
-        // For the pinned stack, the deferring of the multi-window mode changed is tied to the
-        // transition animation into picture-in-picture, and is called once the animation completes,
-        // or is interrupted in a way that would leave the stack in a non-fullscreen state.
-        // @see BoundsAnimationController
-        // @see BoundsAnimationControllerTests
-        return mWindowContainerController.deferScheduleMultiWindowModeChanged();
-    }
-
-    public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
-            boolean forceUpdate) {
-        // It is guaranteed that the activities requiring the update will be in the pinned stack at
-        // this point (either reparented before the animation into PiP, or before reparenting after
-        // the animation out of PiP)
-        synchronized (mService.mGlobalLock) {
-            if (!isAttached()) {
-                return;
-            }
-            ArrayList<TaskRecord> tasks = getAllTasks();
-            for (int i = 0; i < tasks.size(); i++ ) {
-                mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
-                        forceUpdate);
-            }
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
deleted file mode 100644
index 518e39b..0000000
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
-import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
-import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
-import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
-import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
-
-import android.app.RemoteAction;
-import android.graphics.Rect;
-
-import java.util.List;
-
-/**
- * Controller for the pinned stack container. See {@link StackWindowController}.
- */
-public class PinnedStackWindowController extends StackWindowController {
-
-    private Rect mTmpFromBounds = new Rect();
-    private Rect mTmpToBounds = new Rect();
-
-    public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
-            int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
-        super(stackId, listener, displayId, onTop, outBounds, service);
-    }
-
-    /**
-     * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}.  If
-     *         {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the
-     *         default bounds.
-     */
-    public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
-        synchronized (mGlobalLock) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return null;
-            }
-
-            final DisplayContent displayContent = mContainer.getDisplayContent();
-            if (displayContent == null) {
-                return null;
-            }
-
-            final PinnedStackController pinnedStackController =
-                    displayContent.getPinnedStackController();
-            if (stackBounds == null) {
-                // Calculate the aspect ratio bounds from the default bounds
-                stackBounds = pinnedStackController.getDefaultOrLastSavedBounds();
-            }
-
-            if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
-                return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
-                        true /* useCurrentMinEdgeSize */);
-            } else {
-                return stackBounds;
-            }
-        }
-    }
-
-    /**
-     * Animates the pinned stack.
-     */
-    public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
-            int animationDuration, boolean fromFullscreen) {
-        synchronized (mGlobalLock) {
-            if (mContainer == null) {
-                throw new IllegalArgumentException("Pinned stack container not found :(");
-            }
-
-            // Get the from-bounds
-            final Rect fromBounds = new Rect();
-            mContainer.getBounds(fromBounds);
-
-            // Get non-null fullscreen to-bounds for animating if the bounds are null
-            @SchedulePipModeChangedState int schedulePipModeChangedState =
-                NO_PIP_MODE_CHANGED_CALLBACKS;
-            final boolean toFullscreen = toBounds == null;
-            if (toFullscreen) {
-                if (fromFullscreen) {
-                    throw new IllegalArgumentException("Should not defer scheduling PiP mode"
-                            + " change on animation to fullscreen.");
-                }
-                schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
-
-                mService.getStackBounds(
-                        WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
-                if (!mTmpToBounds.isEmpty()) {
-                    // If there is a fullscreen bounds, use that
-                    toBounds = new Rect(mTmpToBounds);
-                } else {
-                    // Otherwise, use the display bounds
-                    toBounds = new Rect();
-                    mContainer.getDisplayContent().getBounds(toBounds);
-                }
-            } else if (fromFullscreen) {
-                schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
-            }
-
-            mContainer.setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
-
-            final Rect finalToBounds = toBounds;
-            final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
-                schedulePipModeChangedState;
-            final DisplayContent displayContent = mContainer.getDisplayContent();
-            displayContent.mBoundsAnimationController.getHandler().post(() -> {
-                if (mContainer == null) {
-                    return;
-                }
-                displayContent.mBoundsAnimationController.animateBounds(mContainer, fromBounds,
-                        finalToBounds, animationDuration, finalSchedulePipModeChangedState,
-                        fromFullscreen, toFullscreen);
-            });
-        }
-    }
-
-    /**
-     * Sets the current picture-in-picture aspect ratio.
-     */
-    public void setPictureInPictureAspectRatio(float aspectRatio) {
-        synchronized (mGlobalLock) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return;
-            }
-
-            final PinnedStackController pinnedStackController =
-                    mContainer.getDisplayContent().getPinnedStackController();
-
-            if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
-                mContainer.getAnimationOrCurrentBounds(mTmpFromBounds);
-                mTmpToBounds.set(mTmpFromBounds);
-                getPictureInPictureBounds(aspectRatio, mTmpToBounds);
-                if (!mTmpToBounds.equals(mTmpFromBounds)) {
-                    animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
-                            -1 /* duration */, false /* fromFullscreen */);
-                }
-                pinnedStackController.setAspectRatio(
-                        pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
-                                ? aspectRatio : -1f);
-            }
-        }
-    }
-
-    /**
-     * Sets the current picture-in-picture actions.
-     */
-    public void setPictureInPictureActions(List<RemoteAction> actions) {
-        synchronized (mGlobalLock) {
-            if (!mService.mSupportsPictureInPicture || mContainer == null) {
-                return;
-            }
-
-            mContainer.getDisplayContent().getPinnedStackController().setActions(actions);
-        }
-    }
-
-    /**
-     * @return whether the multi-window mode change should be deferred as a part of a transition
-     * from fullscreen to non-fullscreen bounds.
-     */
-    public boolean deferScheduleMultiWindowModeChanged() {
-        synchronized (mGlobalLock) {
-            return mContainer.deferScheduleMultiWindowModeChanged();
-        }
-    }
-
-    /**
-     * @return whether the stack can be resized from the bounds animation.
-     */
-    public boolean pinnedStackResizeDisallowed() {
-        synchronized (mGlobalLock) {
-            return mContainer.pinnedStackResizeDisallowed();
-        }
-    }
-
-    /**
-     * The following calls are made from WM to AM.
-     */
-
-    /** Calls directly into activity manager so window manager lock shouldn't held. */
-    public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
-            boolean forceUpdate) {
-        if (mListener != null) {
-            PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
-            listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds,
-                    forceUpdate);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
deleted file mode 100644
index 33e8a60..0000000
--- a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import android.graphics.Rect;
-
-/**
- * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with
- * the stack container.
- */
-public interface PinnedStackWindowListener extends StackWindowListener {
-
-    /**
-     * Called when the stack container pinned stack animation will change the picture-in-picture
-     * mode. This is a direct call into ActivityManager.
-     */
-    default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds,
-            boolean forceUpdate) {}
-}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index f55c7c9..9b72141 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -234,7 +234,7 @@
         mWindowManager = wm;
         setWindowContainer(mWindowManager.mRoot);
         mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
-        mDisplayManager.registerDisplayListener(this, mService.mH);
+        mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
 
         final Display[] displays = mDisplayManager.getDisplays();
@@ -955,7 +955,7 @@
         mWindowManager.deferSurfaceLayout();
 
         final ActivityDisplay display = r.getActivityStack().getDisplay();
-        PinnedActivityStack stack = display.getPinnedStack();
+        ActivityStack stack = display.getPinnedStack();
 
         // This will clear the pinned stack by moving an existing task to the full screen stack,
         // ensuring only one task is present.
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 937c9d9..58cf73a 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -47,10 +47,9 @@
 import android.view.IWindowSession;
 import android.view.IWindowSessionCallback;
 import android.view.InputChannel;
-import android.view.Surface;
+import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
-import android.view.InsetsState;
 import android.view.WindowManager;
 
 import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -432,7 +431,7 @@
 
     @Override
     public void insetsModified(IWindow window, InsetsState state) {
-        synchronized (mService.mWindowMap) {
+        synchronized (mService.mGlobalLock) {
             final WindowState windowState = mService.windowForClientLocked(this, window,
                     false /* throwOnError */);
             if (windowState != null) {
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
deleted file mode 100644
index ada807b..0000000
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ /dev/null
@@ -1,245 +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
- */
-
-package com.android.server.wm;
-
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.ref.WeakReference;
-
-/**
- * Controller for the stack container. This is created by activity manager to link activity stacks
- * to the stack container they use in window manager.
- *
- * Test class: {@link StackWindowControllerTests}
- */
-public class StackWindowController
-        extends WindowContainerController<TaskStack, StackWindowListener> {
-
-    private final int mStackId;
-
-    private final H mHandler;
-
-    final Rect mTmpBounds = new Rect();
-
-    public StackWindowController(int stackId, StackWindowListener listener, int displayId,
-            boolean onTop, Rect outBounds) {
-        this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
-    }
-
-    @VisibleForTesting
-    public StackWindowController(int stackId, StackWindowListener listener,
-            int displayId, boolean onTop, Rect outBounds, WindowManagerService service) {
-        super(listener, service);
-        mStackId = stackId;
-        mHandler = new H(new WeakReference<>(this), service.mH.getLooper());
-
-        final DisplayContent dc = mRoot.getDisplayContent(displayId);
-        if (dc == null) {
-            throw new IllegalArgumentException("Trying to add stackId=" + stackId
-                    + " to unknown displayId=" + displayId);
-        }
-
-        dc.createStack(stackId, onTop, this);
-        getRawBounds(outBounds);
-    }
-
-    @Override
-    public void removeContainer() {
-        if (mContainer != null) {
-            mContainer.removeIfPossible();
-            super.removeContainer();
-        }
-    }
-
-    void reparent(int displayId, Rect outStackBounds, boolean onTop) {
-        if (mContainer == null) {
-            throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId
-                    + " to displayId=" + displayId);
-        }
-
-        final DisplayContent targetDc = mRoot.getDisplayContent(displayId);
-        if (targetDc == null) {
-            throw new IllegalArgumentException("Trying to move stackId=" + mStackId
-                    + " to unknown displayId=" + displayId);
-        }
-
-        targetDc.moveStackToDisplay(mContainer, onTop);
-        getRawBounds(outStackBounds);
-    }
-
-    void positionChildAt(Task child, int position) {
-        if (DEBUG_STACK) {
-            Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position);
-        }
-        if (child == null) {
-            if (DEBUG_STACK) {
-                Slog.i(TAG_WM, "positionChildAt: could not find task=" + this);
-            }
-            return;
-        }
-        if (mContainer == null) {
-            if (DEBUG_STACK) {
-                Slog.i(TAG_WM, "positionChildAt: could not find stack for task=" + mContainer);
-            }
-            return;
-        }
-        child.positionAt(position);
-        mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    void positionChildAtTop(Task child, boolean includingParents) {
-        if (child == null) {
-            // TODO: Fix the call-points that cause this to happen.
-            return;
-        }
-
-        mContainer.positionChildAt(POSITION_TOP, child, includingParents);
-
-        final DisplayContent displayContent = mContainer.getDisplayContent();
-        if (displayContent.mAppTransition.isTransitionSet()) {
-            child.setSendingToBottom(false);
-        }
-        displayContent.layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    void positionChildAtBottom(Task child, boolean includingParents) {
-        if (child == null) {
-            // TODO: Fix the call-points that cause this to happen.
-            return;
-        }
-
-        mContainer.positionChildAt(POSITION_BOTTOM, child, includingParents);
-
-        if (mContainer.getDisplayContent().mAppTransition.isTransitionSet()) {
-            child.setSendingToBottom(true);
-        }
-        mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-    /**
-     * Re-sizes a stack and its containing tasks.
-     *
-     * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
-     * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
-     * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
-     */
-    public void resize(Rect bounds, SparseArray<Rect> taskBounds,
-            SparseArray<Rect> taskTempInsetBounds) {
-        if (mContainer == null) {
-            throw new IllegalArgumentException("resizeStack: stack " + this + " not found.");
-        }
-        // We might trigger a configuration change. Save the current task bounds for freezing.
-        mContainer.prepareFreezingTaskBounds();
-        if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds)
-                && mContainer.isVisible()) {
-            mContainer.getDisplayContent().setLayoutNeeded();
-            mService.mWindowPlacerLocked.performSurfacePlacement();
-        }
-    }
-
-    public void onPipAnimationEndResize() {
-        mContainer.onPipAnimationEndResize();
-    }
-
-    /**
-     * @see TaskStack.getStackDockedModeBoundsLocked(ConfigurationContainer, Rect, Rect, Rect)
-     */
-    public void getStackDockedModeBounds(Configuration parentConfig, Rect dockedBounds,
-            Rect currentTempTaskBounds,
-            Rect outStackBounds, Rect outTempTaskBounds) {
-        if (mContainer != null) {
-            mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds,
-                    currentTempTaskBounds, outStackBounds, outTempTaskBounds);
-            return;
-        }
-        outStackBounds.setEmpty();
-        outTempTaskBounds.setEmpty();
-    }
-
-    public void prepareFreezingTaskBounds() {
-        if (mContainer == null) {
-            throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this
-                    + " not found.");
-        }
-        mContainer.prepareFreezingTaskBounds();
-    }
-
-    public void getRawBounds(Rect outBounds) {
-        if (mContainer.matchParentBounds()) {
-            outBounds.setEmpty();
-        } else {
-            mContainer.getRawBounds(outBounds);
-        }
-    }
-
-    public void getBounds(Rect outBounds) {
-        if (mContainer != null) {
-            mContainer.getBounds(outBounds);
-            return;
-        }
-        outBounds.setEmpty();
-    }
-
-    void requestResize(Rect bounds) {
-        mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
-    }
-
-    @Override
-    public String toString() {
-        return "{StackWindowController stackId=" + mStackId + "}";
-    }
-
-    private static final class H extends Handler {
-
-        static final int REQUEST_RESIZE = 0;
-
-        private final WeakReference<StackWindowController> mController;
-
-        H(WeakReference<StackWindowController> controller, Looper looper) {
-            super(looper);
-            mController = controller;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final StackWindowController controller = mController.get();
-            final StackWindowListener listener = (controller != null)
-                    ? controller.mListener : null;
-            if (listener == null) {
-                return;
-            }
-            switch (msg.what) {
-                case REQUEST_RESIZE:
-                    listener.requestResize((Rect) msg.obj);
-                    break;
-            }
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
deleted file mode 100644
index c763c17..0000000
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import android.graphics.Rect;
-
-/**
- * Interface used by the creator of {@link StackWindowController} to listen to changes with
- * the stack container.
- */
-public interface StackWindowListener extends WindowContainerListener {
-
-    /** Called when the stack container would like its controller to resize. */
-    void requestResize(Rect bounds);
-}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d334bd2..a7dd55b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -209,26 +209,14 @@
         super.removeImmediately();
     }
 
-    void reparent(StackWindowController stackController, int position, boolean moveParents) {
-        if (DEBUG_STACK) {
-            Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId
-                    + " to stack=" + stackController + " at " + position);
-        }
-        final TaskStack stack = stackController.mContainer;
-        if (stack == null) {
-            throw new IllegalArgumentException("reparent: could not find stack="
-                    + stackController);
-        }
-        reparent(stack, position, moveParents);
-        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
-    }
-
-
     void reparent(TaskStack stack, int position, boolean moveParents) {
         if (stack == mStack) {
             throw new IllegalArgumentException(
                     "task=" + this + " already child of stack=" + mStack);
         }
+        if (stack == null) {
+            throw new IllegalArgumentException("reparent: could not find stack.");
+        }
         if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
                 + " from stack=" + mStack);
         EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
@@ -254,6 +242,7 @@
             onDisplayChanged(displayContent);
             prevDisplayContent.setLayoutNeeded();
         }
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
     }
 
     /** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 6acd864..f3050a9 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -709,7 +709,7 @@
 
         final List<TaskRecord> tasksToCheck = new ArrayList<>();
         for (int i = 0; i < display.getChildCount(); ++i) {
-            ActivityStack<?> stack = display.getChildAt(i);
+            final ActivityStack stack = display.getChildAt(i);
             if (!stack.inFreeformWindowingMode()) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 4a553cf..69dcaf4 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -455,17 +455,10 @@
         }
 
         final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
-        final StackWindowController stackController = getStack().getWindowContainerController();
+        final TaskStack stack = getStack().getTaskStack();
 
-        if (DEBUG_STACK) {
-            Slog.i(TAG_WM, "TaskRecord: taskId=" + taskId
-                    + " stack=" + stackController + " bounds=" + bounds);
-        }
-
-        final TaskStack stack = stackController.mContainer;
         if (stack == null) {
-            throw new IllegalArgumentException("TaskRecord: invalid stack="
-                    + stackController);
+            throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
         }
         EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
         mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode,
@@ -742,7 +735,7 @@
 
             // Must reparent first in window manager to avoid a situation where AM can delete the
             // we are coming from in WM before we reparent because it became empty.
-            mTask.reparent(toStack.getWindowContainerController(), position,
+            mTask.reparent(toStack.getTaskStack(), position,
                     moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
 
             final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
@@ -1278,28 +1271,28 @@
     }
 
     /**
-     * Checks if the root activity requires a particular orientation (either by override or
+     * Checks if the top activity requires a particular orientation (either by override or
      * activityInfo) and returns that. Otherwise, this returns ORIENTATION_UNDEFINED.
      */
-    private int getRootActivityRequestedOrientation() {
-        ActivityRecord root = getRootActivity();
+    private int getTopActivityRequestedOrientation() {
+        ActivityRecord top = getTopActivity();
         if (getRequestedOverrideConfiguration().orientation != ORIENTATION_UNDEFINED
-                || root == null) {
+                || top == null) {
             return getRequestedOverrideConfiguration().orientation;
         }
-        int rootScreenOrientation = root.getOrientation();
-        if (rootScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+        int screenOrientation = top.getOrientation();
+        if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
             // NOSENSOR means the display's "natural" orientation, so return that.
             ActivityDisplay display = mStack != null ? mStack.getDisplay() : null;
             if (display != null && display.mDisplayContent != null) {
                 return mStack.getDisplay().mDisplayContent.getNaturalOrientation();
             }
-        } else if (rootScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+        } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
             // LOCKED means the activity's orientation remains unchanged, so return existing value.
-            return root.getConfiguration().orientation;
-        } else if (ActivityInfo.isFixedOrientationLandscape(rootScreenOrientation)) {
+            return top.getConfiguration().orientation;
+        } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)) {
             return ORIENTATION_LANDSCAPE;
-        } else if (ActivityInfo.isFixedOrientationPortrait(rootScreenOrientation)) {
+        } else if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)) {
             return ORIENTATION_PORTRAIT;
         }
         return ORIENTATION_UNDEFINED;
@@ -2196,9 +2189,9 @@
             // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent"
             outOverrideBounds.setEmpty();
 
-            // If the task or its root activity require a different orientation, make it fit the
+            // If the task or its top activity requires a different orientation, make it fit the
             // available bounds by scaling down its bounds.
-            int forcedOrientation = getRootActivityRequestedOrientation();
+            int forcedOrientation = getTopActivityRequestedOrientation();
             if (forcedOrientation != ORIENTATION_UNDEFINED
                     && forcedOrientation != newParentConfig.orientation) {
                 final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index ee74bdf..8ed7d04 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -33,6 +34,10 @@
 import static android.view.WindowManager.DOCKED_RIGHT;
 import static android.view.WindowManager.DOCKED_TOP;
 
+import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
+import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
 import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
@@ -47,10 +52,12 @@
 import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
 import static com.android.server.wm.StackProto.TASKS;
 import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.CallSuper;
+import android.app.RemoteAction;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -71,9 +78,10 @@
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
+import java.util.List;
 
 public class TaskStack extends WindowContainer<Task> implements
-        BoundsAnimationTarget {
+        BoundsAnimationTarget, ConfigurationContainerListener {
     /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
      * restrict IME adjustment so that a min portion of top stack remains visible.*/
     private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
@@ -93,6 +101,10 @@
     private Rect mTmpRect2 = new Rect();
     private Rect mTmpRect3 = new Rect();
 
+    /** For Pinned stack controlling. */
+    private Rect mTmpFromBounds = new Rect();
+    private Rect mTmpToBounds = new Rect();
+
     /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
     private final Rect mAdjustedBounds = new Rect();
 
@@ -141,6 +153,9 @@
 
     private Dimmer mDimmer = new Dimmer(this);
 
+    // TODO: remove after unification.
+    ActivityStack mActivityStack;
+
     /**
      * For {@link #prepareSurfaces}.
      */
@@ -150,10 +165,11 @@
     private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry =
             new AnimatingAppWindowTokenRegistry();
 
-    TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
+    TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) {
         super(service);
         mStackId = stackId;
-        setController(controller);
+        mActivityStack = activityStack;
+        activityStack.registerConfigurationChangeListener(this);
         mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_minimize_thickness);
         EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
@@ -572,6 +588,49 @@
         positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
     }
 
+    void positionChildAt(Task child, int position) {
+        if (DEBUG_STACK) {
+            Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position);
+        }
+        if (child == null) {
+            if (DEBUG_STACK) {
+                Slog.i(TAG_WM, "positionChildAt: could not find task=" + this);
+            }
+            return;
+        }
+        child.positionAt(position);
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+    }
+
+    void positionChildAtTop(Task child, boolean includingParents) {
+        if (child == null) {
+            // TODO: Fix the call-points that cause this to happen.
+            return;
+        }
+
+        positionChildAt(POSITION_TOP, child, includingParents);
+
+        final DisplayContent displayContent = getDisplayContent();
+        if (displayContent.mAppTransition.isTransitionSet()) {
+            child.setSendingToBottom(false);
+        }
+        displayContent.layoutAndAssignWindowLayersIfNeeded();
+    }
+
+    void positionChildAtBottom(Task child, boolean includingParents) {
+        if (child == null) {
+            // TODO: Fix the call-points that cause this to happen.
+            return;
+        }
+
+        positionChildAt(POSITION_BOTTOM, child, includingParents);
+
+        if (getDisplayContent().mAppTransition.isTransitionSet()) {
+            child.setSendingToBottom(true);
+        }
+        getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+    }
+
     @Override
     void positionChildAt(int position, Task child, boolean includingParents) {
         positionChildAt(position, child, includingParents, child.showForAllUsers());
@@ -596,6 +655,21 @@
         EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
     }
 
+    void reparent(int displayId, Rect outStackBounds, boolean onTop) {
+        final DisplayContent targetDc = mWmService.mRoot.getDisplayContent(displayId);
+        if (targetDc == null) {
+            throw new IllegalArgumentException("Trying to move stackId=" + mStackId
+                    + " to unknown displayId=" + displayId);
+        }
+
+        targetDc.moveStackToDisplay(this, onTop);
+        if (matchParentBounds()) {
+            outStackBounds.setEmpty();
+        } else {
+            getRawBounds(outStackBounds);
+        }
+    }
+
     // TODO: We should really have users as a window container in the hierarchy so that we don't
     // have to do complicated things like we are doing in this method.
     private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
@@ -725,6 +799,23 @@
     }
 
     /**
+     * Re-sizes a stack and its containing tasks.
+     *
+     * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen.
+     * @param taskBounds Bounds for tasks in the resized stack, keyed by task id.
+     * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
+     */
+    void resize(Rect bounds, SparseArray<Rect> taskBounds,
+            SparseArray<Rect> taskTempInsetBounds) {
+        // We might trigger a configuration change. Save the current task bounds for freezing.
+        prepareFreezingTaskBounds();
+        if (setBounds(bounds, taskBounds, taskTempInsetBounds) && isVisible()) {
+            getDisplayContent().setLayoutNeeded();
+            mWmService.mWindowPlacerLocked.performSurfacePlacement();
+        }
+    }
+
+    /**
      * Calculate an amount by which to expand the stack bounds in each direction.
      * Used to make room for shadows in the pinned windowing mode.
      */
@@ -929,12 +1020,7 @@
                 (dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds();
         getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds,
                 null /* currentTempTaskBounds */, bounds, tempBounds);
-        getController().requestResize(bounds);
-    }
-
-    @Override
-    StackWindowController getController() {
-        return (StackWindowController) super.getController();
+        mActivityStack.requestResize(bounds);
     }
 
     @Override
@@ -947,6 +1033,14 @@
     }
 
     @Override
+    void removeImmediately() {
+        if (mActivityStack != null) {
+            mActivityStack.unregisterConfigurationChangeListener(this);
+        }
+        super.removeImmediately();
+    }
+
+    @Override
     void onParentSet() {
         super.onParentSet();
 
@@ -1572,14 +1666,13 @@
                 // I don't believe you...
             }
 
-            final PinnedStackWindowController controller =
-                    (PinnedStackWindowController) getController();
-            if (schedulePipModeChangedCallback && controller != null) {
+            if (schedulePipModeChangedCallback && mActivityStack != null) {
                 // We need to schedule the PiP mode change before the animation up. It is possible
                 // in this case for the animation down to not have been completed, so always
                 // force-schedule and update to the client to ensure that it is notified that it
                 // is no longer in picture-in-picture mode
-                controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
+                mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(null,
+                        forceUpdate);
             }
         }
         return true;
@@ -1592,12 +1685,10 @@
             // Update to the final bounds if requested. This is done here instead of in the bounds
             // animator to allow us to coordinate this after we notify the PiP mode changed
 
-            final PinnedStackWindowController controller =
-                    (PinnedStackWindowController) getController();
-            if (schedulePipModeChangedCallback && controller != null) {
+            if (schedulePipModeChangedCallback) {
                 // We need to schedule the PiP mode change after the animation down, so use the
                 // final bounds
-                controller.updatePictureInPictureModeForPinnedStackAnimation(
+                mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(
                         mBoundsAnimationTarget, false /* forceUpdate */);
             }
 
@@ -1624,6 +1715,135 @@
         }
     }
 
+    /**
+     * @return the current stack bounds transformed to the given {@param aspectRatio}. If
+     *         the default bounds is {@code null}, then the {@param aspectRatio} is applied to the
+     *         default bounds.
+     */
+    Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
+        if (!mWmService.mSupportsPictureInPicture) {
+            return null;
+        }
+
+        final DisplayContent displayContent = getDisplayContent();
+        if (displayContent == null) {
+            return null;
+        }
+
+        if (!inPinnedWindowingMode()) {
+            return null;
+        }
+
+        final PinnedStackController pinnedStackController =
+                displayContent.getPinnedStackController();
+        if (stackBounds == null) {
+            // Calculate the aspect ratio bounds from the default bounds
+            stackBounds = pinnedStackController.getDefaultOrLastSavedBounds();
+        }
+
+        if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
+            return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
+                    true /* useCurrentMinEdgeSize */);
+        } else {
+            return stackBounds;
+        }
+    }
+
+    /**
+     * Animates the pinned stack.
+     */
+    void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
+            int animationDuration, boolean fromFullscreen) {
+        if (!inPinnedWindowingMode()) {
+            return;
+        }
+        // Get the from-bounds
+        final Rect fromBounds = new Rect();
+        getBounds(fromBounds);
+
+        // Get non-null fullscreen to-bounds for animating if the bounds are null
+        @SchedulePipModeChangedState int schedulePipModeChangedState =
+                NO_PIP_MODE_CHANGED_CALLBACKS;
+        final boolean toFullscreen = toBounds == null;
+        if (toFullscreen) {
+            if (fromFullscreen) {
+                throw new IllegalArgumentException("Should not defer scheduling PiP mode"
+                        + " change on animation to fullscreen.");
+            }
+            schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
+
+            mWmService.getStackBounds(
+                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
+            if (!mTmpToBounds.isEmpty()) {
+                // If there is a fullscreen bounds, use that
+                toBounds = new Rect(mTmpToBounds);
+            } else {
+                // Otherwise, use the display bounds
+                toBounds = new Rect();
+                getDisplayContent().getBounds(toBounds);
+            }
+        } else if (fromFullscreen) {
+            schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
+        }
+
+        setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
+
+        final Rect finalToBounds = toBounds;
+        final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
+                schedulePipModeChangedState;
+        final DisplayContent displayContent = getDisplayContent();
+        displayContent.mBoundsAnimationController.getHandler().post(() -> {
+            displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
+                    finalToBounds, animationDuration, finalSchedulePipModeChangedState,
+                    fromFullscreen, toFullscreen);
+        });
+    }
+
+    /**
+     * Sets the current picture-in-picture aspect ratio.
+     */
+    void setPictureInPictureAspectRatio(float aspectRatio) {
+        if (!mWmService.mSupportsPictureInPicture) {
+            return;
+        }
+
+        if (!inPinnedWindowingMode()) {
+            return;
+        }
+
+        final PinnedStackController pinnedStackController =
+                getDisplayContent().getPinnedStackController();
+
+        if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
+            return;
+        }
+        getAnimationOrCurrentBounds(mTmpFromBounds);
+        mTmpToBounds.set(mTmpFromBounds);
+        getPictureInPictureBounds(aspectRatio, mTmpToBounds);
+        if (!mTmpToBounds.equals(mTmpFromBounds)) {
+            animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
+                    -1 /* duration */, false /* fromFullscreen */);
+        }
+        pinnedStackController.setAspectRatio(
+                pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+                        ? aspectRatio : -1f);
+    }
+
+    /**
+     * Sets the current picture-in-picture actions.
+     */
+    void setPictureInPictureActions(List<RemoteAction> actions) {
+        if (!mWmService.mSupportsPictureInPicture) {
+            return;
+        }
+
+        if (!inPinnedWindowingMode()) {
+            return;
+        }
+
+        getDisplayContent().getPinnedStackController().setActions(actions);
+    }
+
     @Override
     public boolean isAttached() {
         synchronized (mWmService.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index b219419..9057870 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -67,7 +67,7 @@
                     return;
                 }
                 WindowContainer parent = mDisplayContent.getParent();
-                if (parent != null) {
+                if (parent != null && parent.getTopChild() != mDisplayContent) {
                     parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
                             true /* includingParents */);
                 }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 25e61f8..1905877 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -437,6 +437,7 @@
                 if (mChildren.peekLast() != child) {
                     mChildren.remove(child);
                     mChildren.add(child);
+                    onChildPositionChanged();
                 }
                 if (includingParents && getParent() != null) {
                     getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -447,6 +448,7 @@
                 if (mChildren.peekFirst() != child) {
                     mChildren.remove(child);
                     mChildren.addFirst(child);
+                    onChildPositionChanged();
                 }
                 if (includingParents && getParent() != null) {
                     getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
@@ -460,8 +462,8 @@
                 //       doing this adjustment here and remove any adjustments in the callers.
                 mChildren.remove(child);
                 mChildren.add(position, child);
+                onChildPositionChanged();
         }
-        onChildPositionChanged();
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 90506e7..fda7a85 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -723,7 +723,7 @@
 
         void updateSystemUiSettings() {
             boolean changed;
-            synchronized (mWindowMap) {
+            synchronized (mGlobalLock) {
                 changed = ImmersiveModeConfirmation.loadSetting(mCurrentUserId, mContext)
                         || PolicyControl.reloadFromSetting(mContext);
             }
@@ -2629,12 +2629,23 @@
     @Override
     public void onUserSwitched() {
         mSettingsObserver.updateSystemUiSettings();
-        synchronized (mWindowMap) {
+        synchronized (mGlobalLock) {
             // force a re-application of focused window sysui visibility on each display.
             mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemUiVisibilityLw);
         }
     }
 
+    @Override
+    public void moveDisplayToTop(int displayId) {
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent != null && mRoot.getTopChild() != displayContent) {
+                mRoot.positionChildAt(WindowContainer.POSITION_TOP, displayContent,
+                        true /* includingParents */);
+            }
+        }
+    }
+
     /**
      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
      * performance, only one layout pass should be done. This can be called multiple times, and
@@ -5932,8 +5943,6 @@
                     pw.print(" apps="); pw.print(mAppsFreezingScreen);
             final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked();
             pw.print("  mRotation="); pw.print(defaultDisplayContent.getRotation());
-                    pw.print(" mAltOrientation=");
-                            pw.println(defaultDisplayContent.getAltOrientation());
             pw.print("  mLastWindowForcedOrientation=");
                     pw.print(defaultDisplayContent.getLastWindowForcedOrientation());
                     pw.print(" mLastOrientation=");
@@ -6379,7 +6388,7 @@
     }
 
     void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
-        synchronized (mWindowMap) {
+        synchronized (mGlobalLock) {
             mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
         }
     }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index c8c5e8f..fb00aeb 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -107,6 +107,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
         "android.hardware.gnss@2.0",
+        "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.input.classifier@1.0",
         "android.hardware.ir@1.0",
         "android.hardware.light@2.0",
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index bce944d..dcb2ff5 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -26,6 +26,7 @@
 #include <android/hardware/gnss/1.1/IGnssMeasurement.h>
 #include <android/hardware/gnss/2.0/IGnssMeasurement.h>
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
+#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
 #include <nativehelper/JNIHelp.h>
 #include "jni.h"
 #include "hardware_legacy/power.h"
@@ -88,6 +89,8 @@
 static jmethodID method_correctionPlaneLngDeg;
 static jmethodID method_correctionPlaneAltDeg;
 static jmethodID method_correctionPlaneAzimDeg;
+static jmethodID method_reportNfwNotification;
+static jmethodID method_isInEmergencySession;
 
 /*
  * Save a pointer to JavaVm to attach/detach threads executing
@@ -152,6 +155,9 @@
 using IMeasurementCorrections =
     android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
 
+using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl;
+using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControlCallback;
+
 struct GnssDeathRecipient : virtual public hidl_death_recipient
 {
     // hidl_death_recipient interface
@@ -190,7 +196,7 @@
 // This boolean is needed to ensure that Gnsss Measurement Corrections related method are only
 // initalized when needed which will be few devices initially
 bool firstGnssMeasurementCorrectionInjected = false;
-
+sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
 
@@ -1090,6 +1096,54 @@
 }
 
 /*
+ * GnssVisibilityControlCallback implements callback methods of IGnssVisibilityControlCallback.hal.
+ */
+struct GnssVisibilityControlCallback : public IGnssVisibilityControlCallback {
+    Return<void> nfwNotifyCb(const IGnssVisibilityControlCallback::NfwNotification& notification)
+            override;
+    Return<bool> isInEmergencySession() override;
+};
+
+Return<void> GnssVisibilityControlCallback::nfwNotifyCb(
+        const IGnssVisibilityControlCallback::NfwNotification& notification) {
+    JNIEnv* env = getJniEnv();
+    jstring proxyAppPackageName = env->NewStringUTF(notification.proxyAppPackageName.c_str());
+    jstring otherProtocolStackName = env->NewStringUTF(notification.otherProtocolStackName.c_str());
+    jstring requestorId = env->NewStringUTF(notification.requestorId.c_str());
+
+    if (proxyAppPackageName && otherProtocolStackName && requestorId) {
+        env->CallVoidMethod(mCallbacksObj, method_reportNfwNotification, proxyAppPackageName,
+                            notification.protocolStack, otherProtocolStackName,
+                            notification.requestor, requestorId,
+                            notification.inEmergencyMode, notification.isCachedLocation);
+    } else {
+        ALOGE("%s: OOM Error\n", __func__);
+    }
+
+    if (requestorId) {
+        env->DeleteLocalRef(requestorId);
+    }
+
+    if (otherProtocolStackName) {
+        env->DeleteLocalRef(otherProtocolStackName);
+    }
+
+    if (proxyAppPackageName) {
+        env->DeleteLocalRef(proxyAppPackageName);
+    }
+
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return Void();
+}
+
+Return<bool> GnssVisibilityControlCallback::isInEmergencySession() {
+    JNIEnv* env = getJniEnv();
+    auto result = env->CallBooleanMethod(mCallbacksObj, method_isInEmergencySession);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    return result;
+}
+
+/*
  * AGnssCallback_V1_0 implements callback methods required by the IAGnssCallback 1.0 interface.
  */
 struct AGnssCallback_V1_0 : public IAGnssCallback_V1_0 {
@@ -1323,6 +1377,9 @@
             "reportLocationBatch",
             "([Landroid/location/Location;)V");
     method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
+    method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
+            "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
+    method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z");
 
     /*
      * Save a pointer to JVM.
@@ -1398,12 +1455,6 @@
     if (gnssHal_V2_0 != nullptr) {
         // TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0
         auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
-        auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections();
-        if (!gnssCorrections.isOk()) {
-            ALOGD("Unable to get a handle to GnssMeasurementCorrections interface");
-        } else {
-            gnssCorrectionsIface = gnssCorrections;
-        }
         if (!gnssMeasurement.isOk()) {
             ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
         } else {
@@ -1411,6 +1462,12 @@
             gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
             gnssMeasurementIface = gnssMeasurementIface_V2_0;
         }
+        auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections();
+        if (!gnssCorrections.isOk()) {
+            ALOGD("Unable to get a handle to GnssMeasurementCorrections interface");
+        } else {
+            gnssCorrectionsIface = gnssCorrections;
+        }
     } else if (gnssHal_V1_1 != nullptr) {
          auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
          if (!gnssMeasurement.isOk()) {
@@ -1481,6 +1538,15 @@
     } else {
         gnssBatchingIface = gnssBatching;
     }
+
+    if (gnssHal_V2_0 != nullptr) {
+        auto gnssVisibilityControl = gnssHal_V2_0->getExtensionVisibilityControl();
+        if (!gnssVisibilityControl.isOk()) {
+            ALOGD("Unable to get a handle to GnssVisibilityControl interface");
+        } else {
+            gnssVisibilityControlIface = gnssVisibilityControl;
+        }
+    }
 }
 
 static jboolean android_location_GnssLocationProvider_is_supported(
@@ -1582,7 +1648,13 @@
     if (agnssRilIface != nullptr) {
         agnssRilIface->setCallback(aGnssRilCbIface);
     } else {
-        ALOGI("Unable to Initialize AGnss Ril interface\n");
+        ALOGI("Unable to initialize AGnss Ril interface\n");
+    }
+
+    if (gnssVisibilityControlIface != nullptr) {
+        sp<IGnssVisibilityControlCallback> gnssVisibilityControlCbIface =
+                new GnssVisibilityControlCallback();
+        gnssVisibilityControlIface->setCallback(gnssVisibilityControlCbIface);
     }
 
     return JNI_TRUE;
@@ -1984,6 +2056,11 @@
     return result;
 }
 
+static jboolean android_location_GnssLocationProvider_is_gnss_visibility_control_supported(
+        JNIEnv* /* env */, jclass /* clazz */) {
+    return (gnssVisibilityControlIface != nullptr) ?  JNI_TRUE : JNI_FALSE;
+}
+
 static void android_location_GnssNetworkConnectivityHandler_update_network_state(JNIEnv* env,
                                                                        jobject /* obj */,
                                                                        jboolean connected,
@@ -2567,6 +2644,29 @@
     return gnssBatchingIface->stop();
 }
 
+static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access(
+        JNIEnv* env, jobject, jobjectArray proxyApps) {
+    if (gnssVisibilityControlIface == nullptr) {
+        ALOGI("No GNSS Visibility Control interface available");
+        return JNI_FALSE;
+    }
+
+    const jsize length = env->GetArrayLength(proxyApps);
+    hidl_vec<hidl_string> hidlProxyApps(length);
+    for (int i = 0; i < length; ++i) {
+        jstring proxyApp = (jstring) (env->GetObjectArrayElement(proxyApps, i));
+        ScopedJniString jniProxyApp(env, proxyApp);
+        hidlProxyApps[i] = jniProxyApp;
+    }
+
+    auto result = gnssVisibilityControlIface->enableNfwLocationAccess(hidlProxyApps);
+    if (result.isOk()) {
+        return result;
+    } else {
+        return JNI_FALSE;
+    }
+}
+
 static const JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"class_init_native", "()V", reinterpret_cast<void *>(
@@ -2617,6 +2717,8 @@
     {"native_get_internal_state",
             "()Ljava/lang/String;",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
+    {"native_is_gnss_visibility_control_supported", "()Z", reinterpret_cast<void *>(
+            android_location_GnssLocationProvider_is_gnss_visibility_control_supported)},
 };
 
 static const JNINativeMethod sMethodsBatching[] = {
@@ -2746,6 +2848,14 @@
             reinterpret_cast<void *>(android_location_GnssConfiguration_set_es_extension_sec)},
 };
 
+static const JNINativeMethod sVisibilityControlMethods[] = {
+     /* name, signature, funcPtr */
+    {"native_enable_nfw_location_access",
+            "([Ljava/lang/String;)Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssVisibilityControl_enable_nfw_location_access)},
+};
+
 int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
     jniRegisterNativeMethods(
             env,
@@ -2777,6 +2887,11 @@
             "com/android/server/location/GnssConfiguration",
             sConfigurationMethods,
             NELEM(sConfigurationMethods));
+    jniRegisterNativeMethods(
+            env,
+            "com/android/server/location/GnssVisibilityControl",
+            sVisibilityControlMethods,
+            NELEM(sVisibilityControlMethods));
     return jniRegisterNativeMethods(
             env,
             "com/android/server/location/GnssLocationProvider",
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java
new file mode 100644
index 0000000..eaab650
--- /dev/null
+++ b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreDatabase.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.ipmemorystore;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+/**
+ * Encapsulating class for using the SQLite database backing the memory store.
+ *
+ * This class groups together the contracts and the SQLite helper used to
+ * use the database.
+ *
+ * @hide
+ */
+public class IpMemoryStoreDatabase {
+    /**
+     * Contract class for the Network Attributes table.
+     */
+    public static class NetworkAttributesContract {
+        public static final String TABLENAME = "NetworkAttributes";
+
+        public static final String COLNAME_L2KEY = "l2Key";
+        public static final String COLTYPE_L2KEY = "TEXT NOT NULL";
+
+        public static final String COLNAME_EXPIRYDATE = "expiryDate";
+        // Milliseconds since the Epoch, in true Java style
+        public static final String COLTYPE_EXPIRYDATE = "BIGINT";
+
+        public static final String COLNAME_ASSIGNEDV4ADDRESS = "assignedV4Address";
+        public static final String COLTYPE_ASSIGNEDV4ADDRESS = "INTEGER";
+
+        // Please note that the group hint is only a *hint*, hence its name. The client can offer
+        // this information to nudge the grouping in the decision it thinks is right, but it can't
+        // decide for the memory store what is the same L3 network.
+        public static final String COLNAME_GROUPHINT = "groupHint";
+        public static final String COLTYPE_GROUPHINT = "TEXT";
+
+        public static final String COLNAME_DNSADDRESSES = "dnsAddresses";
+        // Stored in marshalled form as is
+        public static final String COLTYPE_DNSADDRESSES = "BLOB";
+
+        public static final String COLNAME_MTU = "mtu";
+        public static final String COLTYPE_MTU = "INTEGER";
+
+        public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS "
+                + TABLENAME                 + " ("
+                + COLNAME_L2KEY             + " " + COLTYPE_L2KEY + " PRIMARY KEY NOT NULL, "
+                + COLNAME_EXPIRYDATE        + " " + COLTYPE_EXPIRYDATE        + ", "
+                + COLNAME_ASSIGNEDV4ADDRESS + " " + COLTYPE_ASSIGNEDV4ADDRESS + ", "
+                + COLNAME_GROUPHINT         + " " + COLTYPE_GROUPHINT         + ", "
+                + COLNAME_DNSADDRESSES      + " " + COLTYPE_DNSADDRESSES      + ", "
+                + COLNAME_MTU               + " " + COLTYPE_MTU               + ")";
+        public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLENAME;
+    }
+
+    /**
+     * Contract class for the Private Data table.
+     */
+    public static class PrivateDataContract {
+        public static final String TABLENAME = "PrivateData";
+
+        public static final String COLNAME_L2KEY = "l2Key";
+        public static final String COLTYPE_L2KEY = "TEXT NOT NULL";
+
+        public static final String COLNAME_CLIENT = "client";
+        public static final String COLTYPE_CLIENT = "TEXT NOT NULL";
+
+        public static final String COLNAME_DATANAME = "dataName";
+        public static final String COLTYPE_DATANAME = "TEXT NOT NULL";
+
+        public static final String COLNAME_DATA = "data";
+        public static final String COLTYPE_DATA = "BLOB NOT NULL";
+
+        public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS "
+                + TABLENAME        + " ("
+                + COLNAME_L2KEY    + " " + COLTYPE_L2KEY    + ", "
+                + COLNAME_CLIENT   + " " + COLTYPE_CLIENT   + ", "
+                + COLNAME_DATANAME + " " + COLTYPE_DATANAME + ", "
+                + COLNAME_DATA     + " " + COLTYPE_DATA     + ", "
+                + "PRIMARY KEY ("
+                + COLNAME_L2KEY    + ", "
+                + COLNAME_CLIENT   + ", "
+                + COLNAME_DATANAME + "))";
+        public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLENAME;
+    }
+
+    // To save memory when the DB is not used, close it after 30s of inactivity. This is
+    // determined manually based on what feels right.
+    private static final long IDLE_CONNECTION_TIMEOUT_MS = 30_000;
+
+    /** The SQLite DB helper */
+    public static class DbHelper extends SQLiteOpenHelper {
+        // Update this whenever changing the schema.
+        private static final int SCHEMA_VERSION = 1;
+        private static final String DATABASE_FILENAME = "IpMemoryStore.db";
+
+        public DbHelper(@NonNull final Context context) {
+            super(context, DATABASE_FILENAME, null, SCHEMA_VERSION);
+            setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+        }
+
+        /** Called when the database is created */
+        public void onCreate(@NonNull final SQLiteDatabase db) {
+            db.execSQL(NetworkAttributesContract.CREATE_TABLE);
+            db.execSQL(PrivateDataContract.CREATE_TABLE);
+        }
+
+        /** Called when the database is upgraded */
+        public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion,
+                final int newVersion) {
+            // No upgrade supported yet.
+            db.execSQL(NetworkAttributesContract.DROP_TABLE);
+            db.execSQL(PrivateDataContract.DROP_TABLE);
+            onCreate(db);
+        }
+
+        /** Called when the database is downgraded */
+        public void onDowngrade(@NonNull final SQLiteDatabase db, final int oldVersion,
+                final int newVersion) {
+            // Downgrades always nuke all data and recreate an empty table.
+            db.execSQL(NetworkAttributesContract.DROP_TABLE);
+            db.execSQL(PrivateDataContract.DROP_TABLE);
+            onCreate(db);
+        }
+    }
+}
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java
index c9759bf..55a72190 100644
--- a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java
+++ b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/IpMemoryStoreService.java
@@ -19,6 +19,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
 import android.net.IIpMemoryStore;
 import android.net.ipmemorystore.Blob;
 import android.net.ipmemorystore.IOnBlobRetrievedListener;
@@ -27,6 +29,10 @@
 import android.net.ipmemorystore.IOnSameNetworkResponseListener;
 import android.net.ipmemorystore.IOnStatusListener;
 import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.util.Log;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 /**
  * Implementation for the IP memory store.
@@ -37,10 +43,75 @@
  * @hide
  */
 public class IpMemoryStoreService extends IIpMemoryStore.Stub {
-    final Context mContext;
+    private static final String TAG = IpMemoryStoreService.class.getSimpleName();
+    private static final int MAX_CONCURRENT_THREADS = 4;
 
+    @NonNull
+    final Context mContext;
+    @Nullable
+    final SQLiteDatabase mDb;
+    @NonNull
+    final ExecutorService mExecutor;
+
+    /**
+     * Construct an IpMemoryStoreService object.
+     * This constructor will block on disk access to open the database.
+     * @param context the context to access storage with.
+     */
     public IpMemoryStoreService(@NonNull final Context context) {
+        // Note that constructing the service will access the disk and block
+        // for some time, but it should make no difference to the clients. Because
+        // the interface is one-way, clients fire and forget requests, and the callback
+        // will get called eventually in any case, and the framework will wait for the
+        // service to be created to deliver subsequent requests.
+        // Avoiding this would mean the mDb member can't be final, which means the service would
+        // have to test for nullity, care for failure, and allow for a wait at every single access,
+        // which would make the code a lot more complex and require all methods to possibly block.
         mContext = context;
+        SQLiteDatabase db;
+        final IpMemoryStoreDatabase.DbHelper helper = new IpMemoryStoreDatabase.DbHelper(context);
+        try {
+            db = helper.getWritableDatabase();
+            if (null == db) Log.e(TAG, "Unexpected null return of getWriteableDatabase");
+        } catch (final SQLException e) {
+            Log.e(TAG, "Can't open the Ip Memory Store database", e);
+            db = null;
+        } catch (final Exception e) {
+            Log.wtf(TAG, "Impossible exception Ip Memory Store database", e);
+            db = null;
+        }
+        mDb = db;
+        // The work-stealing thread pool executor will spawn threads as needed up to
+        // the max only when there is no free thread available. This generally behaves
+        // exactly like one would expect it intuitively :
+        // - When work arrives, it will spawn a new thread iff there are no available threads
+        // - When there is no work to do it will shutdown threads after a while (the while
+        //   being equal to 2 seconds (not configurable) when max threads are spun up and
+        //   twice as much for every one less thread)
+        // - When all threads are busy the work is enqueued and waits for any worker
+        //   to become available.
+        // Because the stealing pool is made for very heavily parallel execution of
+        // small tasks that spawn others, it creates a queue per thread that in this
+        // case is overhead. However, the three behaviors above make it a superior
+        // choice to cached or fixedThreadPoolExecutor, neither of which can actually
+        // enqueue a task waiting for a thread to be free. This can probably be solved
+        // with judicious subclassing of ThreadPoolExecutor, but that's a lot of dangerous
+        // complexity for little benefit in this case.
+        mExecutor = Executors.newWorkStealingPool(MAX_CONCURRENT_THREADS);
+    }
+
+    /**
+     * Shutdown the memory store service, cancelling running tasks and dropping queued tasks.
+     *
+     * This is provided to give a way to clean up, and is meant to be available in case of an
+     * emergency shutdown.
+     */
+    public void shutdown() {
+        // By contrast with ExecutorService#shutdown, ExecutorService#shutdownNow tries
+        // to cancel the existing tasks, and does not wait for completion. It does not
+        // guarantee the threads can be terminated in any given amount of time.
+        mExecutor.shutdownNow();
+        if (mDb != null) mDb.close();
     }
 
     /**
@@ -61,7 +132,7 @@
     public void storeNetworkAttributes(@NonNull final String l2Key,
             @NonNull final NetworkAttributesParcelable attributes,
             @Nullable final IOnStatusListener listener) {
-        // TODO : implement this
+        // TODO : implement this.
     }
 
     /**
@@ -79,7 +150,7 @@
     public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId,
             @NonNull final String name, @NonNull final Blob data,
             @Nullable final IOnStatusListener listener) {
-        // TODO : implement this
+        // TODO : implement this.
     }
 
     /**
@@ -99,7 +170,7 @@
     @Override
     public void findL2Key(@NonNull final NetworkAttributesParcelable attributes,
             @NonNull final IOnL2KeyResponseListener listener) {
-        // TODO : implement this
+        // TODO : implement this.
     }
 
     /**
@@ -114,7 +185,7 @@
     @Override
     public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
             @NonNull final IOnSameNetworkResponseListener listener) {
-        // TODO : implement this
+        // TODO : implement this.
     }
 
     /**
diff --git a/services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java
new file mode 100644
index 0000000..aa45400
--- /dev/null
+++ b/services/ipmemorystore/java/com/android/server/net/ipmemorystore/RelevanceUtils.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.ipmemorystore;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A class containing the logic around the relevance value for
+ * IP Memory Store.
+ *
+ * @hide
+ */
+public class RelevanceUtils {
+    /**
+     * The relevance is a decaying value that gets lower and lower until it
+     * reaches 0 after some time passes. It follows an exponential decay law,
+     * dropping slowly at first then faster and faster, because a network is
+     * likely to be visited again if it was visited not long ago, and the longer
+     * it hasn't been visited the more likely it is that it won't be visited
+     * again. For example, a network visited on holiday should stay fresh for
+     * the duration of the holiday and persist for a while, but after the venue
+     * hasn't been visited for a while it should quickly be discarded. What
+     * should accelerate forgetting the network is extended periods without
+     * visits, so that occasional venues get discarded but regular visits keep
+     * the network relevant, even if the visits are infrequent.
+     *
+     * This function must be stable by iteration, meaning that adjusting the same value
+     * for different dates iteratively multiple times should give the same result.
+     * Formally, if f is the decay function that associates a relevance x at a date d1
+     * to the value at ulterior date d3, then for any date d2 between d1 and d3 :
+     * f(x, d3 - d1) = f(f(x, d3 - d2), d2 - d1). Intuitively, this property simply
+     * means it should be the same to compute and store back the value after two months,
+     * or to do it once after one month, store it back, and do it again after another
+     * months has passed.
+     * The pair of the relevance and date define the entire curve, so any pair
+     * of values on the curve will define the same curve. Setting one of them to a
+     * constant, so as not to have to store it, means the other one will always suffice
+     * to describe the curve. For example, only storing the date for a known, constant
+     * value of the relevance is an efficient way of remembering this information (and
+     * to compare relevances together, as f is monotonically decreasing).
+     *
+     *** Choosing the function :
+     * Functions of the kind described above are standard exponential decay functions
+     * like the ones that govern atomic decay where the value at any given date can be
+     * computed uniformly from the value at a previous date and the time elapsed since
+     * that date. It is simple to picture this kind of function as one where after a
+     * given period of time called the half-life, the relevance value will have been
+     * halved. Decay of this kind is expressed in function of the previous value by
+     * functions like
+     * f(x, t) = x * F ^ (t / L)
+     * ...where x is the value, t is the elapsed time, L is the half-life (or more
+     * generally the F-th-life) and F the decay factor (typically 0.5, hence why L is
+     * usually called the half-life). The ^ symbol here is used for exponentiation.
+     * Or, starting at a given M for t = 0 :
+     * f(t) = M * F ^ (t / L)
+     *
+     * Because a line in the store needs to become irrelevant at some point but
+     * this class of functions never go to 0, a minimum cutoff has to be chosen to
+     * represent irrelevance. The simpler way of doing this is to simply add this
+     * minimum cutoff to the computation before and removing it after.
+     * Thus the function becomes :
+     * f(x, t) = ((x + K) * F ^ (t / L)) - K
+     * ...where K is the minimum cutoff, L the half-life, and F the factor between
+     * the original x and x after its half-life. Strictly speaking using the word
+     * "half-life" implies that F = 0.5, but the relation works for any value of F.
+     *
+     * It is easy enough to check that this function satisfies the stability
+     * relation that was given above for any value of F, L and K, which become
+     * parameters that can be defined at will.
+     *
+     * relevance
+     *  1.0 |
+     *      |\
+     *      | \
+     *      |  \            (this graph rendered with L = 75 days and K = 1/40)
+     *  0.75|   ',
+     *      |     \
+     *      |      '.
+     *      |        \.
+     *      |          \
+     *  0.5 |           '\
+     *      |             ''.
+     *      |                ''.
+     *      |                   ''.
+     *  0.25|                      '''..
+     *      |                           '''..
+     *      |                                ''''....
+     *      |                                        '''''..........
+     *    0 +-------------------------------------------------------''''''''''----
+     *      0       50       100      150     200      250     300      350     400 days
+     *
+     *** Choosing the parameters
+     * The maximum M is an arbitrary parameter that simply scales the curve.
+     * The tradeoff for M is pretty simple : if the relevance is going to be an
+     * integer, the bigger M is the more precision there is in the relevance.
+     * However, values of M that are easy for humans to read are preferable to
+     * help debugging, and a suitably low value may be enough to ensure there
+     * won't be integer overflows in intermediate computations.
+     * A value of 1_000_000 probably is plenty for precision, while still in the
+     * low range of what ints can represent.
+     *
+     * F and L are parameters to be chosen arbitrarily and have an impact on how
+     * fast the relevance will be decaying at first, keeping in mind that
+     * the 400 days value and the cap stay the same. In simpler words, F and L
+     * define the steepness of the curve.
+     * To keep things simple (and familiar) F is arbitrarily chosen to be 0.5, and
+     * L is set to 200 days visually to achieve the desired effect. Refer to the
+     * illustration above to get a feel of how that feels.
+     *
+     * Moreover, the memory store works on an assumption that the relevance should
+     * be capped, and that an entry with capped relevance should decay in 400 days.
+     * This is on premises that the networks a device will need to remember the
+     * longest should be networks visited about once a year.
+     * For this reason, the relevance is at the maximum M 400 days before expiry :
+     * f(M, 400 days) = 0
+     * From replacing this with the value of the function, K can then be derived
+     * from the values of M, F and L :
+     * (M + K) * F ^ (t / L) - K = 0
+     * K = M * F ^ (400 days / L) / (1 - F ^ (400 days / L))
+     * Replacing with actual values this gives :
+     * K = 1_000_000 * 0.5 ^ (400 / 200) / (1 - 0.5 ^ (400 / 200))
+     *   = 1_000_000 / 3 ≈ 333_333.3
+     * This ensures the function has the desired profile, the desired value at
+     * cap, and the desired value at expiry.
+     *
+     *** Useful relations
+     * Let's define the expiry time for any given relevance x as the interval of
+     * time such as :
+     * f(x, expiry) = 0
+     * which can be rewritten
+     * ((x + K) * F ^ (expiry / L)) = K
+     * ...giving an expression of the expiry in function of the relevance x as
+     * expiry = L * logF(K / (x + K))
+     * Conversely the relevance x can be expressed in function of the expiry as
+     * x = K / F ^ (expiry / L) - K
+     * These relations are useful in utility functions.
+     *
+     *** Bumping things up
+     * The last issue therefore is to decide how to bump up the relevance. The
+     * simple approach is to simply lift up the curve a little bit by a constant
+     * normalized amount, delaying the time of expiry. For example increasing
+     * the relevance by an amount I gives :
+     * x2 = x1 + I
+     * x2 and x1 correspond to two different expiry times expiry2 and expiry1,
+     * and replacing x1 and x2 in the relation above with their expression in
+     * function of the expiry comes :
+     * K / F ^ (expiry2 / L) - K = K / F ^ (expiry1 / L) - K + I
+     * which resolves to :
+     * expiry2 = L * logF(K / (I + K / F ^ (expiry1 / L)))
+     *
+     * In this implementation, the bump is defined as 1/25th of the cap for
+     * the relevance. This means a network will be remembered for the maximum
+     * period of 400 days if connected 25 times in succession not accounting
+     * for decay. Of course decay actually happens so it will take more than 25
+     * connections for any given network to actually reach the cap, but because
+     * decay is slow at first, it is a good estimate of how fast cap happens.
+     *
+     * Specifically, it gives the following four results :
+     * - A network that a device connects to once hits irrelevance about 32.7 days after
+     *   it was first registered if never connected again.
+     * - A network that a device connects to once a day at a fixed hour will hit the cap
+     *   on the 27th connection.
+     * - A network that a device connects to once a week at a fixed hour will hit the cap
+     *   on the 57th connection.
+     * - A network that a device connects to every day for 7 straight days then never again
+     *   expires 144 days after the last connection.
+     * These metrics tend to match pretty well the requirements.
+     */
+
+    // TODO : make these constants configurable at runtime. Don't forget to build it so that
+    // changes will wipe the database, migrate the values, or otherwise make sure the relevance
+    // values are still meaningful.
+
+    // How long, in milliseconds, is a capped relevance valid for, or in other
+    // words how many milliseconds after its relevance was set to RELEVANCE_CAP does
+    // any given line expire. 400 days.
+    @VisibleForTesting
+    public static final long CAPPED_RELEVANCE_LIFETIME_MS = 400L * 24 * 60 * 60 * 1000;
+
+    // The constant that represents a normalized 1.0 value for the relevance. In other words,
+    // the cap for the relevance. This is referred to as M in the explanation above.
+    @VisibleForTesting
+    public static final int CAPPED_RELEVANCE = 1_000_000;
+
+    // The decay factor. After a half-life, the relevance will have decayed by this value.
+    // This is referred to as F in the explanation above.
+    private static final double DECAY_FACTOR = 0.5;
+
+    // The half-life. After this time, the relevance will have decayed by a factor DECAY_FACTOR.
+    // This is referred to as L in the explanation above.
+    private static final long HALF_LIFE_MS = 200L * 24 * 60 * 60 * 1000;
+
+    // The value of the frame change. This is referred to as K in the explanation above.
+    private static final double IRRELEVANCE_FLOOR =
+            CAPPED_RELEVANCE * powF((double) CAPPED_RELEVANCE_LIFETIME_MS / HALF_LIFE_MS)
+            / (1 - powF((double) CAPPED_RELEVANCE_LIFETIME_MS / HALF_LIFE_MS));
+
+    // How much to bump the relevance by every time a line is written to.
+    @VisibleForTesting
+    public static final int RELEVANCE_BUMP = CAPPED_RELEVANCE / 25;
+
+    // Java doesn't include a function for the logarithm in an arbitrary base, so implement it
+    private static final double LOG_DECAY_FACTOR = Math.log(DECAY_FACTOR);
+    private static double logF(final double value) {
+        return Math.log(value) / LOG_DECAY_FACTOR;
+    }
+
+    // Utility function to get a power of the decay factor, to simplify the code.
+    private static double powF(final double value) {
+        return Math.pow(DECAY_FACTOR, value);
+    }
+
+    /**
+     * Compute the value of the relevance now given an expiry date.
+     *
+     * @param expiry the date at which the column in the database expires.
+     * @return the adjusted value of the relevance for this moment in time.
+     */
+    public static int computeRelevanceForNow(final long expiry) {
+        return computeRelevanceForTargetDate(expiry, System.currentTimeMillis());
+    }
+
+    /**
+     * Compute the value of the relevance at a given date from an expiry date.
+     *
+     * Because relevance decays with time, a relevance in the past corresponds to
+     * a different relevance later.
+     *
+     * Relevance is always a positive value. 0 means not relevant at all.
+     *
+     * See the explanation at the top of this file to get the justification for this
+     * computation.
+     *
+     * @param expiry the date at which the column in the database expires.
+     * @param target the target date to adjust the relevance to.
+     * @return the adjusted value of the relevance for the target moment.
+     */
+    public static int computeRelevanceForTargetDate(final long expiry, final long target) {
+        final long delay = expiry - target;
+        if (delay >= CAPPED_RELEVANCE_LIFETIME_MS) return CAPPED_RELEVANCE;
+        if (delay <= 0) return 0;
+        return (int) (IRRELEVANCE_FLOOR / powF((float) delay / HALF_LIFE_MS) - IRRELEVANCE_FLOOR);
+    }
+
+    /**
+     * Compute the expiry duration adjusted up for a new fresh write.
+     *
+     * Every time data is written to the memory store for a given line, the
+     * relevance is bumped up by a certain amount, which will boost the priority
+     * of this line for computation of group attributes, and delay (possibly
+     * indefinitely, if the line is accessed regularly) forgetting the data stored
+     * in that line.
+     * As opposed to bumpExpiryDate, this function uses a duration from now to expiry.
+     *
+     * See the explanation at the top of this file for a justification of this computation.
+     *
+     * @param oldExpiryDuration the old expiry duration in milliseconds from now.
+     * @return the expiry duration representing a bumped up relevance value.
+     */
+    public static long bumpExpiryDuration(final long oldExpiryDuration) {
+        // L * logF(K / (I + K / F ^ (expiry1 / L))), as documented above
+        final double divisionFactor = powF(((double) oldExpiryDuration) / HALF_LIFE_MS);
+        final double oldRelevance = IRRELEVANCE_FLOOR / divisionFactor;
+        final long newDuration =
+                (long) (HALF_LIFE_MS * logF(IRRELEVANCE_FLOOR / (RELEVANCE_BUMP + oldRelevance)));
+        return Math.min(newDuration, CAPPED_RELEVANCE_LIFETIME_MS);
+    }
+
+    /**
+     * Compute the new expiry date adjusted up for a new fresh write.
+     *
+     * Every time data is written to the memory store for a given line, the
+     * relevance is bumped up by a certain amount, which will boost the priority
+     * of this line for computation of group attributes, and delay (possibly
+     * indefinitely, if the line is accessed regularly) forgetting the data stored
+     * in that line.
+     * As opposed to bumpExpiryDuration, this function takes the old timestamp and returns the
+     * new timestamp.
+     *
+     * {@see bumpExpiryDuration}, and keep in mind that the bump depends on when this is called,
+     * because the relevance decays exponentially, therefore bumping up a high relevance (for a
+     * date far in the future) is less potent than bumping up a low relevance (for a date in
+     * a close future).
+     *
+     * @param oldExpiryDate the old date of expiration.
+     * @return the new expiration date after the relevance bump.
+     */
+    public static long bumpExpiryDate(final long oldExpiryDate) {
+        final long now = System.currentTimeMillis();
+        final long newDuration = bumpExpiryDuration(oldExpiryDate - now);
+        return now + newDuration;
+    }
+}
diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
new file mode 100644
index 0000000..5b77f54
--- /dev/null
+++ b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.shared;
+
+import static android.net.shared.ParcelableUtil.fromParcelableArray;
+import static android.net.shared.ParcelableUtil.toParcelableArray;
+
+import android.annotation.Nullable;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.IpPrefixParcelable;
+import android.net.LinkAddress;
+import android.net.LinkAddressParcelable;
+import android.net.LinkProperties;
+import android.net.LinkPropertiesParcelable;
+import android.net.ProxyInfo;
+import android.net.ProxyInfoParcelable;
+import android.net.RouteInfo;
+import android.net.RouteInfoParcelable;
+import android.net.Uri;
+
+import java.net.InetAddress;
+import java.util.Arrays;
+
+/**
+ * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties
+ * and its attributes.
+ * @hide
+ */
+public final class LinkPropertiesParcelableUtil {
+
+    /**
+     * Convert a ProxyInfo to a ProxyInfoParcelable
+     */
+    public static ProxyInfoParcelable toStableParcelable(@Nullable ProxyInfo proxyInfo) {
+        if (proxyInfo == null) {
+            return null;
+        }
+        final ProxyInfoParcelable parcel = new ProxyInfoParcelable();
+        parcel.host = proxyInfo.getHost();
+        parcel.port = proxyInfo.getPort();
+        parcel.exclusionList = proxyInfo.getExclusionList();
+        parcel.pacFileUrl = proxyInfo.getPacFileUrl().toString();
+        return parcel;
+    }
+
+    /**
+     * Convert a ProxyInfoParcelable to a ProxyInfo
+     */
+    public static ProxyInfo fromStableParcelable(@Nullable ProxyInfoParcelable parcel) {
+        if (parcel == null) {
+            return null;
+        }
+        if (Uri.EMPTY.toString().equals(parcel.pacFileUrl)) {
+            return ProxyInfo.buildDirectProxy(
+                    parcel.host, parcel.port, Arrays.asList(parcel.exclusionList));
+        } else {
+            return ProxyInfo.buildPacProxy(Uri.parse(parcel.pacFileUrl));
+        }
+    }
+
+    /**
+     * Convert an IpPrefixParcelable to an IpPrefix
+     */
+    public static IpPrefixParcelable toStableParcelable(@Nullable IpPrefix ipPrefix) {
+        if (ipPrefix == null) {
+            return null;
+        }
+        final IpPrefixParcelable parcel = new IpPrefixParcelable();
+        parcel.address = ipPrefix.getAddress().getHostAddress();
+        parcel.prefixLength = ipPrefix.getPrefixLength();
+        return parcel;
+    }
+
+    /**
+     * Convert an IpPrefix to an IpPrefixParcelable
+     */
+    public static IpPrefix fromStableParcelable(@Nullable IpPrefixParcelable parcel) {
+        if (parcel == null) {
+            return null;
+        }
+        return new IpPrefix(InetAddresses.parseNumericAddress(parcel.address), parcel.prefixLength);
+    }
+
+    /**
+     * Convert a RouteInfoParcelable to a RouteInfo
+     */
+    public static RouteInfoParcelable toStableParcelable(@Nullable RouteInfo routeInfo) {
+        if (routeInfo == null) {
+            return null;
+        }
+        final RouteInfoParcelable parcel = new RouteInfoParcelable();
+        parcel.destination = toStableParcelable(routeInfo.getDestination());
+        parcel.gatewayAddr = routeInfo.getGateway().getHostAddress();
+        parcel.ifaceName = routeInfo.getInterface();
+        parcel.type = routeInfo.getType();
+        return parcel;
+    }
+
+    /**
+     * Convert a RouteInfo to a RouteInfoParcelable
+     */
+    public static RouteInfo fromStableParcelable(@Nullable RouteInfoParcelable parcel) {
+        if (parcel == null) {
+            return null;
+        }
+        final IpPrefix destination = fromStableParcelable(parcel.destination);
+        return new RouteInfo(
+                destination, InetAddresses.parseNumericAddress(parcel.gatewayAddr),
+                parcel.ifaceName, parcel.type);
+    }
+
+    /**
+     * Convert a LinkAddressParcelable to a LinkAddress
+     */
+    public static LinkAddressParcelable toStableParcelable(@Nullable LinkAddress la) {
+        if (la == null) {
+            return null;
+        }
+        final LinkAddressParcelable parcel = new LinkAddressParcelable();
+        parcel.address = la.getAddress().getHostAddress();
+        parcel.prefixLength = la.getPrefixLength();
+        parcel.flags = la.getFlags();
+        parcel.scope = la.getScope();
+        return parcel;
+    }
+
+    /**
+     * Convert a LinkAddress to a LinkAddressParcelable
+     */
+    public static LinkAddress fromStableParcelable(@Nullable LinkAddressParcelable parcel) {
+        if (parcel == null) {
+            return null;
+        }
+        return new LinkAddress(
+                InetAddresses.parseNumericAddress(parcel.address),
+                parcel.prefixLength,
+                parcel.flags,
+                parcel.scope);
+    }
+
+    /**
+     * Convert a LinkProperties to a LinkPropertiesParcelable
+     */
+    public static LinkPropertiesParcelable toStableParcelable(@Nullable LinkProperties lp) {
+        if (lp == null) {
+            return null;
+        }
+        final LinkPropertiesParcelable parcel = new LinkPropertiesParcelable();
+        parcel.ifaceName = lp.getInterfaceName();
+        parcel.linkAddresses = toParcelableArray(
+                lp.getLinkAddresses(),
+                LinkPropertiesParcelableUtil::toStableParcelable,
+                LinkAddressParcelable.class);
+        parcel.dnses = toParcelableArray(
+                lp.getDnsServers(), InetAddress::getHostAddress, String.class);
+        parcel.pcscfs = toParcelableArray(
+                lp.getPcscfServers(), InetAddress::getHostAddress, String.class);
+        parcel.validatedPrivateDnses = toParcelableArray(
+                lp.getValidatedPrivateDnsServers(), InetAddress::getHostAddress, String.class);
+        parcel.usePrivateDns = lp.isPrivateDnsActive();
+        parcel.privateDnsServerName = lp.getPrivateDnsServerName();
+        parcel.domains = lp.getDomains();
+        parcel.routes = toParcelableArray(
+                lp.getRoutes(), LinkPropertiesParcelableUtil::toStableParcelable,
+                RouteInfoParcelable.class);
+        parcel.httpProxy = toStableParcelable(lp.getHttpProxy());
+        parcel.mtu = lp.getMtu();
+        parcel.tcpBufferSizes = lp.getTcpBufferSizes();
+        parcel.nat64Prefix = toStableParcelable(lp.getNat64Prefix());
+        parcel.stackedLinks = toParcelableArray(
+                lp.getStackedLinks(), LinkPropertiesParcelableUtil::toStableParcelable,
+                LinkPropertiesParcelable.class);
+        return parcel;
+    }
+
+    /**
+     * Convert a LinkPropertiesParcelable to a LinkProperties
+     */
+    public static LinkProperties fromStableParcelable(@Nullable LinkPropertiesParcelable parcel) {
+        if (parcel == null) {
+            return null;
+        }
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(parcel.ifaceName);
+        lp.setLinkAddresses(fromParcelableArray(parcel.linkAddresses,
+                LinkPropertiesParcelableUtil::fromStableParcelable));
+        lp.setDnsServers(fromParcelableArray(parcel.dnses, InetAddresses::parseNumericAddress));
+        lp.setPcscfServers(fromParcelableArray(parcel.pcscfs, InetAddresses::parseNumericAddress));
+        lp.setValidatedPrivateDnsServers(
+                fromParcelableArray(parcel.validatedPrivateDnses,
+                InetAddresses::parseNumericAddress));
+        lp.setUsePrivateDns(parcel.usePrivateDns);
+        lp.setPrivateDnsServerName(parcel.privateDnsServerName);
+        lp.setDomains(parcel.domains);
+        for (RouteInfoParcelable route : parcel.routes) {
+            lp.addRoute(fromStableParcelable(route));
+        }
+        lp.setHttpProxy(fromStableParcelable(parcel.httpProxy));
+        lp.setMtu(parcel.mtu);
+        lp.setTcpBufferSizes(parcel.tcpBufferSizes);
+        lp.setNat64Prefix(fromStableParcelable(parcel.nat64Prefix));
+        for (LinkPropertiesParcelable stackedLink : parcel.stackedLinks) {
+            lp.addStackedLink(fromStableParcelable(stackedLink));
+        }
+        return lp;
+    }
+}
diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java
new file mode 100644
index 0000000..a18976c
--- /dev/null
+++ b/services/net/java/android/net/shared/ParcelableUtil.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.shared;
+
+import android.annotation.NonNull;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * Utility methods to help convert to/from stable parcelables.
+ * @hide
+ */
+public final class ParcelableUtil {
+    // Below methods could be implemented easily with streams, but streams are frowned upon in
+    // frameworks code.
+
+    /**
+     * Convert a list of BaseType items to an array of ParcelableType items using the specified
+     * converter function.
+     */
+    public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray(
+            @NonNull List<BaseType> base,
+            @NonNull Function<BaseType, ParcelableType> conv,
+            @NonNull Class<ParcelableType> parcelClass) {
+        final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size());
+        int i = 0;
+        for (BaseType b : base) {
+            out[i] = conv.apply(b);
+            i++;
+        }
+        return out;
+    }
+
+    /**
+     * Convert an array of ParcelableType items to a list of BaseType items using the specified
+     * converter function.
+     */
+    public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray(
+            @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) {
+        final ArrayList<BaseType> out = new ArrayList<>(parceled.length);
+        for (ParcelableType t : parceled) {
+            out.add(conv.apply(t));
+        }
+        return out;
+    }
+}
diff --git a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
index 7559560..9a6e003 100644
--- a/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/TransportManagerTest.java
@@ -58,7 +58,9 @@
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.transport.TransportClientManager;
 import com.android.server.backup.transport.TransportNotRegisteredException;
+import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -66,6 +68,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
@@ -75,6 +78,7 @@
 import java.util.stream.Stream;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowApplicationPackageManager.class})
 @Presubmit
 public class TransportManagerTest {
     private static final String PACKAGE_A = "some.package.a";
@@ -102,6 +106,12 @@
         mTransportB1 = genericTransport(PACKAGE_B, "TransportBaz");
     }
 
+    /** Reset shadow state. */
+    @After
+    public void tearDown() throws Exception {
+        ShadowApplicationPackageManager.reset();
+    }
+
     @Test
     public void testRegisterTransports() throws Exception {
         setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
@@ -666,7 +676,8 @@
         packageInfo.packageName = packageName;
         packageInfo.applicationInfo = new ApplicationInfo();
         packageInfo.applicationInfo.privateFlags = flags;
-        mShadowPackageManager.addPackage(packageInfo);
+        mShadowPackageManager.installPackage(packageInfo);
+        ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo);
     }
 
     private TransportManager createTransportManagerWithRegisteredTransports(
diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
index 3b7fa3d..427aed7 100644
--- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -514,10 +514,14 @@
     private void setUpForUpdateTransportAttributes() throws Exception {
         mTransportComponent = mTransport.getTransportComponent();
         String transportPackage = mTransportComponent.getPackageName();
+        PackageInfo packageInfo = getPackageInfo(transportPackage);
 
         ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager());
-        shadowPackageManager.addPackage(transportPackage);
+        shadowPackageManager.installPackage(packageInfo);
         shadowPackageManager.setPackagesForUid(PACKAGE_UID, transportPackage);
+        // Set up for user invocations on ApplicationPackageManager.
+        ShadowApplicationPackageManager.addInstalledPackage(transportPackage, packageInfo);
+        ShadowApplicationPackageManager.setPackageUid(transportPackage, PACKAGE_UID);
 
         mTransportUid = mContext.getPackageManager().getPackageUid(transportPackage, 0);
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
index dc32209..ab121ed 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java
@@ -38,6 +38,7 @@
         extends org.robolectric.shadows.ShadowApplicationPackageManager {
     private static final Map<String, PackageInfo> sPackageInfos = new ArrayMap<>();
     private static final List<PackageInfo> sInstalledPackages = new ArrayList<>();
+    private static final Map<String, Integer> sPackageUids = new ArrayMap<>();
 
     /**
      * Registers the package {@code packageName} to be returned when invoking {@link
@@ -49,6 +50,14 @@
         sInstalledPackages.add(packageInfo);
     }
 
+    /**
+     * Sets the package uid {@code packageUid} for the package {@code packageName} to be returned
+     * when invoking {@link ApplicationPackageManager#getPackageUidAsUser(String, int, int)}.
+     */
+    public static void setPackageUid(String packageName, int packageUid) {
+        sPackageUids.put(packageName, packageUid);
+    }
+
     @Override
     protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
             throws NameNotFoundException {
@@ -63,6 +72,15 @@
         return sInstalledPackages;
     }
 
+    @Override
+    protected int getPackageUidAsUser(String packageName, int flags, int userId)
+            throws NameNotFoundException {
+        if (!sPackageUids.containsKey(packageName)) {
+            throw new NameNotFoundException(packageName);
+        }
+        return sPackageUids.get(packageName);
+    }
+
     /** Clear package state. */
     @Resetter
     public static void reset() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index f1cd0cd..57ee6dc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -33,6 +33,7 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -43,7 +44,12 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
+import android.app.AppGlobals;
+import android.app.IActivityManager;
+import android.app.IUidObserver;
 import android.app.job.JobInfo;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
@@ -56,13 +62,16 @@
 import android.os.BatteryManagerInternal;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.SparseBooleanArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobSchedulerService.Constants;
+import com.android.server.job.JobStore;
 import com.android.server.job.controllers.QuotaController.ExecutionStats;
 import com.android.server.job.controllers.QuotaController.TimingSession;
 
@@ -96,9 +105,13 @@
     private BroadcastReceiver mChargingReceiver;
     private Constants mConstants;
     private QuotaController mQuotaController;
+    private int mSourceUid;
+    private IUidObserver mUidObserver;
 
     private MockitoSession mMockingSession;
     @Mock
+    private ActivityManagerInternal mActivityMangerInternal;
+    @Mock
     private AlarmManager mAlarmManager;
     @Mock
     private Context mContext;
@@ -107,6 +120,8 @@
     @Mock
     private UsageStatsManagerInternal mUsageStatsManager;
 
+    private JobStore mJobStore;
+
     @Before
     public void setUp() {
         mMockingSession = mockitoSession()
@@ -123,8 +138,17 @@
         when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
         when(mJobSchedulerService.getConstants()).thenReturn(mConstants);
         // Called in QuotaController constructor.
+        IActivityManager activityManager = ActivityManager.getService();
+        spyOn(activityManager);
+        try {
+            doNothing().when(activityManager).registerUidObserver(any(), anyInt(), anyInt(), any());
+        } catch (RemoteException e) {
+            fail("registerUidObserver threw exception: " + e.getMessage());
+        }
         when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
         when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+        doReturn(mActivityMangerInternal)
+                .when(() -> LocalServices.getService(ActivityManagerInternal.class));
         doReturn(mock(BatteryManagerInternal.class))
                 .when(() -> LocalServices.getService(BatteryManagerInternal.class));
         doReturn(mUsageStatsManager)
@@ -132,6 +156,9 @@
         // Used in JobStatus.
         doReturn(mock(PackageManagerInternal.class))
                 .when(() -> LocalServices.getService(PackageManagerInternal.class));
+        // Used in QuotaController.Handler.
+        mJobStore = JobStore.initAndGetForTesting(mContext, mContext.getFilesDir());
+        when(mJobSchedulerService.getJobStore()).thenReturn(mJobStore);
 
         // Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
         // in the past, and QuotaController sometimes floors values at 0, so if the test time
@@ -150,10 +177,23 @@
         // Capture the listeners.
         ArgumentCaptor<BroadcastReceiver> receiverCaptor =
                 ArgumentCaptor.forClass(BroadcastReceiver.class);
+        ArgumentCaptor<IUidObserver> uidObserverCaptor =
+                ArgumentCaptor.forClass(IUidObserver.class);
         mQuotaController = new QuotaController(mJobSchedulerService);
 
         verify(mContext).registerReceiver(receiverCaptor.capture(), any());
         mChargingReceiver = receiverCaptor.getValue();
+        try {
+            verify(activityManager).registerUidObserver(
+                    uidObserverCaptor.capture(),
+                    eq(ActivityManager.UID_OBSERVER_PROCSTATE),
+                    eq(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE),
+                    any());
+            mUidObserver = uidObserverCaptor.getValue();
+            mSourceUid = AppGlobals.getPackageManager().getPackageUid(SOURCE_PACKAGE, 0, 0);
+        } catch (RemoteException e) {
+            fail(e.getMessage());
+        }
     }
 
     @After
@@ -182,6 +222,25 @@
         mChargingReceiver.onReceive(mContext, intent);
     }
 
+    private void setProcessState(int procState) {
+        try {
+            doReturn(procState).when(mActivityMangerInternal).getUidProcessState(mSourceUid);
+            SparseBooleanArray foregroundUids = mQuotaController.getForegroundUids();
+            spyOn(foregroundUids);
+            mUidObserver.onUidStateChanged(mSourceUid, procState, 0);
+            if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+                verify(foregroundUids, timeout(SECOND_IN_MILLIS).times(1))
+                        .put(eq(mSourceUid), eq(true));
+                assertTrue(foregroundUids.get(mSourceUid));
+            } else {
+                verify(foregroundUids, timeout(SECOND_IN_MILLIS).times(1)).delete(eq(mSourceUid));
+                assertFalse(foregroundUids.get(mSourceUid));
+            }
+        } catch (RemoteException e) {
+            fail("registerUidObserver threw exception: " + e.getMessage());
+        }
+    }
+
     private void setStandbyBucket(int bucketIndex) {
         int bucket;
         switch (bucketIndex) {
@@ -204,9 +263,18 @@
                 anyLong())).thenReturn(bucket);
     }
 
-    private void setStandbyBucket(int bucketIndex, JobStatus job) {
+    private void setStandbyBucket(int bucketIndex, JobStatus... jobs) {
         setStandbyBucket(bucketIndex);
-        job.setStandbyBucket(bucketIndex);
+        for (JobStatus job : jobs) {
+            job.setStandbyBucket(bucketIndex);
+        }
+    }
+
+    private void trackJobs(JobStatus... jobs) {
+        for (JobStatus job : jobs) {
+            mJobStore.add(job);
+            mQuotaController.maybeStartTrackingJobLocked(job, null);
+        }
     }
 
     private JobStatus createJobStatus(String testTag, int jobId) {
@@ -214,8 +282,11 @@
                 new ComponentName(mContext, "TestQuotaJobService"))
                 .setMinimumLatency(Math.abs(jobId) + 1)
                 .build();
-        return JobStatus.createFromJobInfo(
+        JobStatus js = JobStatus.createFromJobInfo(
                 jobInfo, CALLING_UID, SOURCE_PACKAGE, SOURCE_USER_ID, testTag);
+        // Make sure tests aren't passing just because the default bucket is likely ACTIVE.
+        js.setStandbyBucket(FREQUENT_INDEX);
+        return js;
     }
 
     private TimingSession createTimingSession(long start, long duration, int count) {
@@ -709,6 +780,7 @@
         verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
 
         JobStatus jobStatus = createJobStatus("testMaybeScheduleStartAlarmLocked_Active", 1);
+        setStandbyBucket(standbyBucket, jobStatus);
         mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
         mQuotaController.prepareForExecutionLocked(jobStatus);
         advanceElapsedClock(5 * MINUTE_IN_MILLIS);
@@ -1339,19 +1411,23 @@
         setDischarging();
 
         JobStatus jobStatus = createJobStatus("testTimerTracking_AllForeground", 1);
-        jobStatus.uidActive = true;
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
         mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
 
         assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         mQuotaController.prepareForExecutionLocked(jobStatus);
         advanceElapsedClock(5 * SECOND_IN_MILLIS);
+        // Change to a state that should still be considered foreground.
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        advanceElapsedClock(5 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobStatus, null, false);
         assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
-     * Tests that Timers properly track overlapping foreground and background jobs.
+     * Tests that Timers properly track sessions when switching between foreground and background
+     * states.
      */
     @Test
     public void testTimerTracking_ForegroundAndBackground() {
@@ -1360,7 +1436,6 @@
         JobStatus jobBg1 = createJobStatus("testTimerTracking_ForegroundAndBackground", 1);
         JobStatus jobBg2 = createJobStatus("testTimerTracking_ForegroundAndBackground", 2);
         JobStatus jobFg3 = createJobStatus("testTimerTracking_ForegroundAndBackground", 3);
-        jobFg3.uidActive = true;
         mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
         mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
         mQuotaController.maybeStartTrackingJobLocked(jobFg3, null);
@@ -1368,6 +1443,7 @@
         List<TimingSession> expected = new ArrayList<>();
 
         // UID starts out inactive.
+        setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
         long start = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.prepareForExecutionLocked(jobBg1);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
@@ -1379,48 +1455,223 @@
 
         // Bg job starts while inactive, spans an entire active session, and ends after the
         // active session.
-        // Fg job starts after the bg job and ends before the bg job.
-        // Entire bg job duration should be counted since it started before active session. However,
-        // count should only be 1 since Timer shouldn't count fg jobs.
+        // App switching to foreground state then fg job starts.
+        // App remains in foreground state after coming to foreground, so there should only be one
+        // session.
         start = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
         mQuotaController.prepareForExecutionLocked(jobBg2);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
         mQuotaController.prepareForExecutionLocked(jobFg3);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobFg3, null, false);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
-        expected.add(createTimingSession(start, 30 * SECOND_IN_MILLIS, 1));
         assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
 
         advanceElapsedClock(SECOND_IN_MILLIS);
 
         // Bg job 1 starts, then fg job starts. Bg job 1 job ends. Shortly after, uid goes
         // "inactive" and then bg job 2 starts. Then fg job ends.
-        // This should result in two TimingSessions with a count of one each.
+        // This should result in two TimingSessions:
+        //  * The first should have a count of 1
+        //  * The second should have a count of 2 since it will include both jobs
         start = JobSchedulerService.sElapsedRealtimeClock.millis();
         mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
         mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
         mQuotaController.maybeStartTrackingJobLocked(jobFg3, null);
+        setProcessState(ActivityManager.PROCESS_STATE_LAST_ACTIVITY);
         mQuotaController.prepareForExecutionLocked(jobBg1);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
         mQuotaController.prepareForExecutionLocked(jobFg3);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobBg1, jobBg1, true);
-        expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 1));
         advanceElapsedClock(10 * SECOND_IN_MILLIS); // UID "inactive" now
         start = JobSchedulerService.sElapsedRealtimeClock.millis();
+        setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
         mQuotaController.prepareForExecutionLocked(jobBg2);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobFg3, null, false);
         advanceElapsedClock(10 * SECOND_IN_MILLIS);
         mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
-        expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 1));
+        expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
         assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
     }
 
     /**
+     * Tests that Timers properly track overlapping top and background jobs.
+     */
+    @Test
+    public void testTimerTracking_TopAndNonTop() {
+        setDischarging();
+
+        JobStatus jobBg1 = createJobStatus("testTimerTracking_TopAndNonTop", 1);
+        JobStatus jobBg2 = createJobStatus("testTimerTracking_TopAndNonTop", 2);
+        JobStatus jobFg1 = createJobStatus("testTimerTracking_TopAndNonTop", 3);
+        JobStatus jobTop = createJobStatus("testTimerTracking_TopAndNonTop", 4);
+        mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
+        mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
+        mQuotaController.maybeStartTrackingJobLocked(jobFg1, null);
+        mQuotaController.maybeStartTrackingJobLocked(jobTop, null);
+        assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+        List<TimingSession> expected = new ArrayList<>();
+
+        // UID starts out inactive.
+        setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        long start = JobSchedulerService.sElapsedRealtimeClock.millis();
+        mQuotaController.prepareForExecutionLocked(jobBg1);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobBg1, jobBg1, true);
+        expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(SECOND_IN_MILLIS);
+
+        // Bg job starts while inactive, spans an entire active session, and ends after the
+        // active session.
+        // App switching to top state then fg job starts.
+        // App remains in top state after coming to top, so there should only be one
+        // session.
+        start = JobSchedulerService.sElapsedRealtimeClock.millis();
+        mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
+        mQuotaController.prepareForExecutionLocked(jobBg2);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        mQuotaController.prepareForExecutionLocked(jobTop);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobTop, null, false);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
+        assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+        advanceElapsedClock(SECOND_IN_MILLIS);
+
+        // Bg job 1 starts, then top job starts. Bg job 1 job ends. Then app goes to
+        // foreground_service and a new job starts. Shortly after, uid goes
+        // "inactive" and then bg job 2 starts. Then top job ends, followed by bg and fg jobs.
+        // This should result in two TimingSessions:
+        //  * The first should have a count of 1
+        //  * The second should have a count of 2, which accounts for the bg2 and fg, but not top
+        //    jobs.
+        start = JobSchedulerService.sElapsedRealtimeClock.millis();
+        mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
+        mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
+        mQuotaController.maybeStartTrackingJobLocked(jobTop, null);
+        setProcessState(ActivityManager.PROCESS_STATE_LAST_ACTIVITY);
+        mQuotaController.prepareForExecutionLocked(jobBg1);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        mQuotaController.prepareForExecutionLocked(jobTop);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobBg1, jobBg1, true);
+        advanceElapsedClock(5 * SECOND_IN_MILLIS);
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        mQuotaController.prepareForExecutionLocked(jobFg1);
+        advanceElapsedClock(5 * SECOND_IN_MILLIS);
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS); // UID "inactive" now
+        start = JobSchedulerService.sElapsedRealtimeClock.millis();
+        setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+        mQuotaController.prepareForExecutionLocked(jobBg2);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobTop, null, false);
+        advanceElapsedClock(10 * SECOND_IN_MILLIS);
+        mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
+        mQuotaController.maybeStopTrackingJobLocked(jobFg1, null, false);
+        expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
+        assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+    }
+
+    /**
+     * Tests that TOP jobs aren't stopped when an app runs out of quota.
+     */
+    @Test
+    public void testTracking_OutOfQuota_ForegroundAndBackground() {
+        setDischarging();
+
+        JobStatus jobBg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 1);
+        JobStatus jobTop = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 2);
+        trackJobs(jobBg, jobTop);
+        setStandbyBucket(WORKING_INDEX, jobTop, jobBg); // 2 hour window
+        // Now the package only has 20 seconds to run.
+        final long remainingTimeMs = 20 * SECOND_IN_MILLIS;
+        mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+                createTimingSession(
+                        JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS,
+                        10 * MINUTE_IN_MILLIS - remainingTimeMs, 1));
+
+        InOrder inOrder = inOrder(mJobSchedulerService);
+
+        // UID starts out inactive.
+        setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+        // Start the job.
+        mQuotaController.prepareForExecutionLocked(jobBg);
+        advanceElapsedClock(remainingTimeMs / 2);
+        // New job starts after UID is in the foreground. Since the app is now in the foreground, it
+        // should continue to have remainingTimeMs / 2 time remaining.
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        mQuotaController.prepareForExecutionLocked(jobTop);
+        advanceElapsedClock(remainingTimeMs);
+
+        // Wait for some extra time to allow for job processing.
+        inOrder.verify(mJobSchedulerService,
+                timeout(remainingTimeMs + 2 * SECOND_IN_MILLIS).times(0))
+                .onControllerStateChanged();
+        assertEquals(remainingTimeMs / 2, mQuotaController.getRemainingExecutionTimeLocked(jobBg));
+        assertEquals(remainingTimeMs / 2, mQuotaController.getRemainingExecutionTimeLocked(jobTop));
+        // Go to a background state.
+        setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+        advanceElapsedClock(remainingTimeMs / 2 + 1);
+        inOrder.verify(mJobSchedulerService,
+                timeout(remainingTimeMs / 2 + 2 * SECOND_IN_MILLIS).times(1))
+                .onControllerStateChanged();
+        // Top job should still be allowed to run.
+        assertFalse(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+        // New jobs to run.
+        JobStatus jobBg2 = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 3);
+        JobStatus jobTop2 = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 4);
+        JobStatus jobFg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 5);
+        setStandbyBucket(WORKING_INDEX, jobBg2, jobTop2, jobFg);
+
+        advanceElapsedClock(20 * SECOND_IN_MILLIS);
+        setProcessState(ActivityManager.PROCESS_STATE_TOP);
+        inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+                .onControllerStateChanged();
+        trackJobs(jobFg, jobTop);
+        mQuotaController.prepareForExecutionLocked(jobTop);
+        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+        // App still in foreground so everything should be in quota.
+        advanceElapsedClock(20 * SECOND_IN_MILLIS);
+        setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+        advanceElapsedClock(20 * SECOND_IN_MILLIS);
+        setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+        inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+                .onControllerStateChanged();
+        // App is now in background and out of quota. Fg should now change to out of quota since it
+        // wasn't started. Top should remain in quota since it started when the app was in TOP.
+        assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertFalse(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        assertFalse(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+        trackJobs(jobBg2);
+        assertFalse(jobBg2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+    }
+
+    /**
      * Tests that a job is properly updated and JobSchedulerService is notified when a job reaches
      * its quota.
      */
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
index 8b0e8ab..eb9b98e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -147,6 +148,7 @@
         mTestLooper.dispatchAll();
     }
 
+    @Ignore("b/120845532")
     @Test
     public void arcInitiation_requestActiveSource() {
         mSendCecCommandSuccess = true;
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 93a09dc..5d8131f 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -40,7 +40,6 @@
 import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -142,7 +141,6 @@
         assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
     }
 
-    @Ignore("b/110413065 Support multiple device types 4 and 5.")
     @Test
     public void testAllocatLogicalAddress_PlaybackPreferredNotOccupied() {
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback);
@@ -158,7 +156,6 @@
         assertEquals(ADDR_PLAYBACK_2, mLogicalAddress);
     }
 
-    @Ignore("b/110413065 Support multiple device types 4 and 5.")
     @Test
     public void testAllocatLogicalAddress_PlaybackNoPreferredNotOcuppied() {
         mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 3b51a2a..3a6cdc2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -21,6 +21,7 @@
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
+import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
 import static com.android.server.hdmi.Constants.ADDR_TUNER_1;
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -29,9 +30,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiPortInfo;
 import android.media.AudioManager;
 import android.os.Looper;
-import android.os.SystemProperties;
 import android.os.test.TestLooper;
 
 import androidx.test.InstrumentationRegistry;
@@ -46,7 +47,6 @@
 import org.junit.runners.JUnit4;
 
 import java.util.ArrayList;
-
 @SmallTest
 @RunWith(JUnit4.class)
 /** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */
@@ -67,9 +67,15 @@
     private int mMusicVolume;
     private int mMusicMaxVolume;
     private boolean mMusicMute;
-    private int mAvrPhysicalAddress;
+    private static final int SELF_PHYSICAL_ADDRESS = 0x2000;
+    private static final int HDMI_1_PHYSICAL_ADDRESS = 0x2100;
+    private static final int HDMI_2_PHYSICAL_ADDRESS = 0x2200;
+    private static final int HDMI_3_PHYSICAL_ADDRESS = 0x2300;
     private int mInvokeDeviceEventState;
     private HdmiDeviceInfo mDeviceInfo;
+    private boolean mMutingEnabled;
+    private boolean mArcSupport;
+    private HdmiPortInfo[] mHdmiPortInfo;
 
     @Before
     public void setUp() {
@@ -141,9 +147,20 @@
                 }
 
                 @Override
-                int pathToPortId(int path) {
-                    // port id is not useful for the test right now
-                    return 1;
+                void writeStringSetting(String key, String value) {
+                    // do nothing
+                }
+
+                @Override
+                boolean readBooleanSetting(String key, boolean defVal) {
+                    switch (key) {
+                        case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE:
+                            return mMutingEnabled;
+                        case Constants.PROPERTY_ARC_SUPPORT:
+                            return mArcSupport;
+                        default:
+                            return defVal;
+                    }
                 }
             };
 
@@ -154,11 +171,17 @@
             void setIsActiveSource(boolean on) {
                 mIsActiveSource = on;
             }
+
+            @Override
+            protected int getPreferredAddress() {
+                return ADDR_PLAYBACK_1;
+            }
         };
         mHdmiCecLocalDeviceAudioSystem.init();
         mHdmiCecLocalDevicePlayback.init();
         mHdmiControlService.setIoLooper(mMyLooper);
         mNativeWrapper = new FakeNativeWrapper();
+        mNativeWrapper.setPhysicalAddress(SELF_PHYSICAL_ADDRESS);
         mHdmiCecController =
             HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper);
         mHdmiControlService.setCecController(mHdmiCecController);
@@ -166,15 +189,28 @@
         mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
         mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
         mLocalDevices.add(mHdmiCecLocalDevicePlayback);
+        mHdmiCecLocalDeviceAudioSystem.setRoutingControlFeatureEnables(true);
+        mHdmiPortInfo = new HdmiPortInfo[4];
+        mHdmiPortInfo[0] =
+            new HdmiPortInfo(
+                0, HdmiPortInfo.PORT_INPUT, SELF_PHYSICAL_ADDRESS, true, false, false);
+        mHdmiPortInfo[1] =
+            new HdmiPortInfo(
+                2, HdmiPortInfo.PORT_INPUT, HDMI_1_PHYSICAL_ADDRESS, true, false, false);
+        mHdmiPortInfo[2] =
+            new HdmiPortInfo(
+                1, HdmiPortInfo.PORT_INPUT, HDMI_2_PHYSICAL_ADDRESS, true, false, false);
+        mHdmiPortInfo[3] =
+            new HdmiPortInfo(
+                4, HdmiPortInfo.PORT_INPUT, HDMI_3_PHYSICAL_ADDRESS, true, false, false);
+        mNativeWrapper.setPortInfo(mHdmiPortInfo);
         mHdmiControlService.initPortInfo();
         // No TV device interacts with AVR so system audio control won't be turned on here
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mTestLooper.dispatchAll();
         mNativeWrapper.clearResultMessages();
-        mAvrPhysicalAddress  = 0x2000;
-        mNativeWrapper.setPhysicalAddress(mAvrPhysicalAddress);
-        SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "true");
-        SystemProperties.set(Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, "true");
+        mMutingEnabled = true;
+        mArcSupport = true;
         mInvokeDeviceEventState = 0;
         mDeviceInfo = null;
     }
@@ -244,6 +280,8 @@
         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
     }
 
+    // Testing device has sadConfig.xml
+    @Ignore("b/120845532")
     @Test
     public void handleRequestShortAudioDescriptor_noAudioDeviceInfo() throws Exception {
         HdmiCecMessage expectedMessage =
@@ -414,51 +452,6 @@
     }
 
     @Test
-    public void pathToPort_isMe() throws Exception {
-        int targetPhysicalAddress = 0x1000;
-        mNativeWrapper.setPhysicalAddress(0x1000);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(0);
-    }
-
-    @Test
-    public void pathToPort_isBelow() throws Exception {
-        int targetPhysicalAddress = 0x1100;
-        mNativeWrapper.setPhysicalAddress(0x1000);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(1);
-    }
-
-    @Test
-    public void pathToPort_neitherMeNorBelow() throws Exception {
-        int targetPhysicalAddress = 0x3000;
-        mNativeWrapper.setPhysicalAddress(0x2000);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(-1);
-
-        targetPhysicalAddress = 0x2200;
-        mNativeWrapper.setPhysicalAddress(0x3300);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(-1);
-
-        targetPhysicalAddress = 0x2213;
-        mNativeWrapper.setPhysicalAddress(0x2212);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(-1);
-
-        targetPhysicalAddress = 0x2340;
-        mNativeWrapper.setPhysicalAddress(0x2310);
-        assertThat(mHdmiCecLocalDeviceAudioSystem
-                .getLocalPortFromPhysicalAddress(targetPhysicalAddress))
-                .isEqualTo(-1);
-    }
-
-    @Test
     public void handleRequestArcInitiate_isNotDirectConnectedToTv() throws Exception {
         HdmiCecMessage message =
                 HdmiCecMessageBuilder.buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM);
@@ -530,7 +523,7 @@
                         ADDR_TV,
                         Constants.MESSAGE_REQUEST_ARC_INITIATION,
                         Constants.ABORT_UNRECOGNIZED_OPCODE);
-        SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "false");
+        mArcSupport = false;
 
         assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)).isTrue();
         mTestLooper.dispatchAll();
@@ -541,7 +534,7 @@
         HdmiCecMessage message =
                 HdmiCecMessageBuilder.buildSystemAudioModeRequest(
                         ADDR_TUNER_1, ADDR_AUDIO_SYSTEM,
-                        mAvrPhysicalAddress, true);
+                        SELF_PHYSICAL_ADDRESS, true);
         HdmiCecMessage expectedMessage =
                 HdmiCecMessageBuilder.buildFeatureAbortCommand(
                         ADDR_AUDIO_SYSTEM,
@@ -559,7 +552,7 @@
         HdmiCecMessage message =
                 HdmiCecMessageBuilder.buildSystemAudioModeRequest(
                         ADDR_TUNER_1, ADDR_AUDIO_SYSTEM,
-                        mAvrPhysicalAddress, true);
+                        SELF_PHYSICAL_ADDRESS, true);
         HdmiCecMessage expectedMessage =
                 HdmiCecMessageBuilder.buildSetSystemAudioMode(
                         ADDR_AUDIO_SYSTEM, Constants.ADDR_BROADCAST, true);
@@ -585,15 +578,14 @@
             .isEqualTo(expectedActiveSource);
     }
 
-    @Ignore("b/110413065 Support multiple device types 4 and 5.")
     @Test
     public void handleRoutingChange_currentActivePortIsHome() {
         HdmiCecMessage message =
-                HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, mAvrPhysicalAddress);
+                HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, SELF_PHYSICAL_ADDRESS);
 
         HdmiCecMessage expectedMessage =
-                HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, mAvrPhysicalAddress);
-        ActiveSource expectedActiveSource = ActiveSource.of(ADDR_PLAYBACK_1, mAvrPhysicalAddress);
+                HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, SELF_PHYSICAL_ADDRESS);
+        ActiveSource expectedActiveSource = ActiveSource.of(ADDR_PLAYBACK_1, SELF_PHYSICAL_ADDRESS);
         int expectedLocalActivePort = Constants.CEC_SWITCH_HOME;
 
         assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingChange(message)).isTrue();
@@ -608,17 +600,18 @@
     @Test
     public void handleRoutingInformation_currentActivePortIsHDMI1() {
         HdmiCecMessage message =
-                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000);
-        mHdmiCecLocalDeviceAudioSystem.setRoutingPort(Constants.CEC_SWITCH_HDMI1);
+                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, SELF_PHYSICAL_ADDRESS);
+        mHdmiCecLocalDeviceAudioSystem.setRoutingPort(mHdmiPortInfo[1].getId());
         HdmiCecMessage expectedMessage =
-                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100);
+                HdmiCecMessageBuilder.buildRoutingInformation(
+                        ADDR_AUDIO_SYSTEM, HDMI_1_PHYSICAL_ADDRESS);
 
         assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingInformation(message)).isTrue();
         mTestLooper.dispatchAll();
         assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
     }
 
-    @Ignore("b/110413065 Support multiple device types 4 and 5.")
+    @Ignore("b/120845532")
     @Test
     public void handleRoutingChange_homeIsActive_playbackSendActiveSource() {
         HdmiCecMessage message =
@@ -667,7 +660,7 @@
         mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice);
 
         HdmiDeviceInfo differentDevice = new HdmiDeviceInfo(
-                ADDR_PLAYBACK_1, 0x2100, 4, HdmiDeviceInfo.DEVICE_PLAYBACK,
+                ADDR_PLAYBACK_1, 0x2300, 4, HdmiDeviceInfo.DEVICE_PLAYBACK,
                 Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_1));
 
         mHdmiCecLocalDeviceAudioSystem.updateCecDevice(differentDevice);
@@ -686,14 +679,13 @@
         mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice);
 
         HdmiDeviceInfo differentDevice = new HdmiDeviceInfo(
-                ADDR_PLAYBACK_1, 0x2200, 1, HdmiDeviceInfo.DEVICE_PLAYBACK,
-                Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_1));
+                ADDR_PLAYBACK_2, 0x2200, 1, HdmiDeviceInfo.DEVICE_PLAYBACK,
+                Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_2));
         HdmiCecMessage reportPhysicalAddress = HdmiCecMessageBuilder
                 .buildReportPhysicalAddressCommand(
-                        ADDR_PLAYBACK_1, 0x2200, HdmiDeviceInfo.DEVICE_PLAYBACK);
+                        ADDR_PLAYBACK_2, 0x2200, HdmiDeviceInfo.DEVICE_PLAYBACK);
         mHdmiCecLocalDeviceAudioSystem.handleReportPhysicalAddress(reportPhysicalAddress);
 
-        mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice);
         mTestLooper.dispatchAll();
         assertThat(mDeviceInfo).isEqualTo(differentDevice);
         assertThat(mHdmiCecLocalDeviceAudioSystem
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 792c617..feae4ee 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -81,7 +81,8 @@
         mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress);
     }
 
-    @Ignore
+    // Playback device does not handle routing control related feature right now
+    @Ignore("b/120845532")
     @Test
     public void handleSetStreamPath_underCurrentDevice() {
         assertThat(mHdmiCecLocalDevicePlayback.getLocalActivePath()).isEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 67ce13f..1f66074 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -179,6 +179,7 @@
     @Test
     public void pathToPort_pathExists_weAreNonTv() {
         mNativeWrapper.setPhysicalAddress(0x2000);
+        mHdmiControlService.initPortInfo();
         assertThat(mHdmiControlService.pathToPortId(0x2120)).isEqualTo(1);
         assertThat(mHdmiControlService.pathToPortId(0x2234)).isEqualTo(2);
     }
@@ -186,6 +187,7 @@
     @Test
     public void pathToPort_pathExists_weAreTv() {
         mNativeWrapper.setPhysicalAddress(0x0000);
+        mHdmiControlService.initPortInfo();
         assertThat(mHdmiControlService.pathToPortId(0x2120)).isEqualTo(3);
         assertThat(mHdmiControlService.pathToPortId(0x3234)).isEqualTo(4);
     }
@@ -193,6 +195,7 @@
     @Test
     public void pathToPort_pathInvalid() {
         mNativeWrapper.setPhysicalAddress(0x2000);
+        mHdmiControlService.initPortInfo();
         assertThat(mHdmiControlService.pathToPortId(0x1000)).isEqualTo(Constants.INVALID_PORT_ID);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
new file mode 100644
index 0000000..985c647
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.hdmi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.util.Slog;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.hdmi.HdmiUtils.CodecSad;
+import com.android.server.hdmi.HdmiUtils.DeviceConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/** Tests for {@link HdmiUtils} class. */
+public class HdmiUtilsTest {
+
+    private static final String TAG = "HdmiUtilsTest";
+
+    private final String mExampleXML =
+            "<!-- A sample Short Audio Descriptor configuration xml -->"
+                    + "<config version=\"1.0\" xmlns:xi=\"http://www.w3.org/2001/XInclude\">"
+                    + "<device type=\"VX_AUDIO_DEVICE_IN_HDMI_ARC\">"
+                    + "<supportedFormat format=\"AUDIO_FORMAT_LPCM\" descriptor=\"011a03\"/>"
+                    + "<supportedFormat format=\"AUDIO_FORMAT_DD\" descriptor=\"0d0506\"/>"
+                    + "</device>"
+                    + "<device type=\"AUDIO_DEVICE_IN_SPDIF\">"
+                    + "<supportedFormat format=\"AUDIO_FORMAT_LPCM\" descriptor=\"010203\"/>"
+                    + "<supportedFormat format=\"AUDIO_FORMAT_DD\" descriptor=\"040506\"/>"
+                    + "</device>"
+                    + "</config>";
+
+    @Test
+    public void pathToPort_isMe() {
+        int targetPhysicalAddress = 0x1000;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                        HdmiUtils.TARGET_SAME_PHYSICAL_ADDRESS);
+    }
+
+    @Test
+    public void pathToPort_isDirectlyBelow() {
+        int targetPhysicalAddress = 0x1100;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
+    }
+
+    @Test
+    public void pathToPort_isBelow() {
+        int targetPhysicalAddress = 0x1110;
+        int myPhysicalAddress = 0x1000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1);
+    }
+
+    @Test
+    public void pathToPort_neitherMeNorBelow() {
+        int targetPhysicalAddress = 0x3000;
+        int myPhysicalAddress = 0x2000;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                        HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2200;
+        myPhysicalAddress = 0x3300;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                        HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2213;
+        myPhysicalAddress = 0x2212;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                        HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+
+        targetPhysicalAddress = 0x2340;
+        myPhysicalAddress = 0x2310;
+        assertThat(HdmiUtils.getLocalPortFromPhysicalAddress(
+                targetPhysicalAddress, myPhysicalAddress)).isEqualTo(
+                        HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE);
+    }
+
+    @Test
+    public void parseSampleXML() {
+        List<DeviceConfig> config = new ArrayList<>();
+        try {
+            config = HdmiUtils.ShortAudioDescriptorXmlParser.parse(
+                    new ByteArrayInputStream(mExampleXML.getBytes(StandardCharsets.UTF_8)));
+        } catch (IOException e) {
+            Slog.e(TAG, e.getMessage(), e);
+        } catch (XmlPullParserException e) {
+            Slog.e(TAG, e.getMessage(), e);
+        }
+
+        CodecSad expectedCodec1 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "011a03");
+        CodecSad expectedCodec2 = new CodecSad(Constants.AUDIO_CODEC_DD, "0d0506");
+        CodecSad expectedCodec3 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "010203");
+        CodecSad expectedCodec4 = new CodecSad(Constants.AUDIO_CODEC_DD, "040506");
+
+        List<CodecSad> expectedList1 = new ArrayList<>();
+        expectedList1.add(expectedCodec1);
+        expectedList1.add(expectedCodec2);
+
+        List<CodecSad> expectedList2 = new ArrayList<>();
+        expectedList2.add(expectedCodec3);
+        expectedList2.add(expectedCodec4);
+
+        DeviceConfig expectedDevice1 = new DeviceConfig(
+                "VX_AUDIO_DEVICE_IN_HDMI_ARC", expectedList1);
+        DeviceConfig expectedDevice2 = new DeviceConfig(
+                "AUDIO_DEVICE_IN_SPDIF", expectedList2);
+
+        List<DeviceConfig> expectedConfig = new ArrayList<>();
+        expectedConfig.add(expectedDevice1);
+        expectedConfig.add(expectedDevice2);
+
+        assertThat(config).isEqualTo(expectedConfig);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
index bd297ee..440a49a 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java
@@ -31,6 +31,7 @@
 import androidx.test.filters.SmallTest;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -150,6 +151,11 @@
                             int sourceAddress, int physicalAddress) {
                         mBroadcastActiveSource = true;
                     }
+
+                    @Override
+                    int pathToPortId(int path) {
+                        return -1;
+                    }
                 };
         mHdmiCecLocalDeviceAudioSystem =
                 new HdmiCecLocalDeviceAudioSystem(hdmiControlService) {
@@ -270,6 +276,7 @@
         assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated());
     }
 
+    @Ignore("b/120845532")
     @Test
     public void testIsPlaybackDevice_cannotReceiveActiveSource() {
         resetTestVariables();
@@ -282,10 +289,10 @@
         mTestLooper.dispatchAll();
 
         assertThat(mMsgRequestActiveSourceCount).isEqualTo(1);
-        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
-        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
-        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue();
         assertThat(mBroadcastActiveSource).isTrue();
+        assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1);
+        assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1);
+        assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue();
     }
 
     private void resetTestVariables() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 823b7a5..3ebc6ad 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -544,6 +544,18 @@
         switchUser(-1, UserHandle.of(startUser), false);
     }
 
+    public void testSwitchUserByHandle_ThrowsException() {
+        synchronized (mUserSwitchLock) {
+            try {
+                ActivityManager am = getContext().getSystemService(ActivityManager.class);
+                am.switchUser(null);
+                fail("Expected IllegalArgumentException on passing in a null UserHandle.");
+            } catch (IllegalArgumentException expected) {
+                // Do nothing - exception is expected.
+            }
+        }
+    }
+
     @MediumTest
     public void testConcurrentUserCreate() throws Exception {
         int userCount = mUserManager.getUserCount();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
index 3b6b48b..f817e8e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
@@ -77,7 +77,6 @@
 
     @Mock IPackageManager mPM;
     @Mock Installer mInstaller;
-    private final Object mInstallLock = new Object();
 
     private PackageDynamicCodeLoading mPackageDynamicCodeLoading;
     private DexLogger mDexLogger;
@@ -103,7 +102,7 @@
         };
 
         // For test purposes capture log messages as well as sending to the event log.
-        mDexLogger = new DexLogger(mPM, mInstaller, mInstallLock, mPackageDynamicCodeLoading) {
+        mDexLogger = new DexLogger(mPM, mInstaller, mPackageDynamicCodeLoading) {
             @Override
                 void writeDclEvent(int uid, String message) {
                     super.writeDclEvent(uid, message);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 5bf3d2d..56f4a85 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -36,6 +36,9 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
 
 import android.platform.test.annotations.Presubmit;
 
@@ -54,11 +57,6 @@
 @Presubmit
 public class ActivityDisplayTests extends ActivityTestsBase {
 
-    @Before
-    public void setUp() throws Exception {
-        setupActivityTaskManagerService();
-    }
-
     @Test
     public void testLastFocusedStackIsUpdatedWhenMovingStack() {
         // Create a stack at bottom.
@@ -277,4 +275,60 @@
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
         assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
     }
+
+    @Test
+    public void testRemoveStackInWindowingModes() {
+        removeStackTests(() -> mRootActivityContainer.removeStacksInWindowingModes(
+                WINDOWING_MODE_FULLSCREEN));
+    }
+
+    @Test
+    public void testRemoveStackWithActivityTypes() {
+        removeStackTests(
+                () -> mRootActivityContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD));
+    }
+
+    private void removeStackTests(Runnable runnable) {
+        final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+        final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, ON_TOP);
+        final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, ON_TOP);
+        final ActivityStack stack3 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, ON_TOP);
+        final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_STANDARD, ON_TOP);
+        final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor).setStack(
+                stack1).setTaskId(1).build();
+        final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor).setStack(
+                stack2).setTaskId(2).build();
+        final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor).setStack(
+                stack3).setTaskId(3).build();
+        final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor).setStack(
+                stack4).setTaskId(4).build();
+
+        // Reordering stacks while removing stacks.
+        doAnswer(invocation -> {
+            display.positionChildAtTop(stack3, false);
+            return true;
+        }).when(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
+                any());
+
+        // Removing stacks from the display while removing stacks.
+        doAnswer(invocation -> {
+            display.removeChild(stack2);
+            return true;
+        }).when(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
+                any());
+
+        runnable.run();
+        verify(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
+                any());
+        verify(mSupervisor).removeTaskByIdLocked(eq(task3.taskId), anyBoolean(), anyBoolean(),
+                any());
+        verify(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
+                any());
+        verify(mSupervisor).removeTaskByIdLocked(eq(task1.taskId), anyBoolean(), anyBoolean(),
+                any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index cac9cf6..ee22861 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -70,8 +70,6 @@
 
     @Before
     public void setUpAMLO() throws Exception {
-        setupActivityTaskManagerService();
-
         mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
 
         // ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8f9d2ba..8be63fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -19,8 +19,10 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -39,11 +41,14 @@
 import static org.junit.Assert.assertTrue;
 
 import android.app.ActivityOptions;
+import android.app.servertransaction.ActivityConfigurationChangeItem;
 import android.app.servertransaction.ClientTransaction;
 import android.app.servertransaction.PauseActivityItem;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.util.MergedConfiguration;
 import android.util.MutableBoolean;
 
 import androidx.test.filters.MediumTest;
@@ -67,8 +72,7 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
-        mStack = new StackBuilder(mRootActivityContainer).build();
+        mStack = (TestActivityStack) new StackBuilder(mRootActivityContainer).build();
         mTask = mStack.getChildAt(0);
         mActivity = mTask.getTopActivity();
     }
@@ -251,4 +255,112 @@
         assertEquals(prevSeq + 1, appWindowTokenRequestedOrientation.seq);
         verify(mActivity.mAppWindowToken).onMergedOverrideConfigurationChanged();
     }
+
+    @Test
+    public void testSetsRelaunchReason_NotDragResizing() {
+        mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
+
+        mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
+        mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
+                mActivity.getConfiguration()));
+
+        mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+        final Configuration newConfig = new Configuration(mTask.getConfiguration());
+        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
+                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        mTask.onRequestedOverrideConfigurationChanged(newConfig);
+
+        mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+
+        mActivity.ensureActivityConfiguration(0, false, false);
+
+        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE,
+                mActivity.mRelaunchReason);
+    }
+
+    @Test
+    public void testSetsRelaunchReason_DragResizing() {
+        mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
+
+        mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
+        mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
+                mActivity.getConfiguration()));
+
+        mActivity.info.configChanges &= ~ActivityInfo.CONFIG_ORIENTATION;
+        final Configuration newConfig = new Configuration(mTask.getConfiguration());
+        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
+                ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
+        mTask.onRequestedOverrideConfigurationChanged(newConfig);
+
+        doReturn(true).when(mTask.getTask()).isDragResizing();
+
+        mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+
+        mActivity.ensureActivityConfiguration(0, false, false);
+
+        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE,
+                mActivity.mRelaunchReason);
+    }
+
+    @Test
+    public void testSetsRelaunchReason_NonResizeConfigChanges() {
+        mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
+
+        mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
+        mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
+                mActivity.getConfiguration()));
+
+        mActivity.info.configChanges &= ~ActivityInfo.CONFIG_FONT_SCALE;
+        final Configuration newConfig = new Configuration(mTask.getConfiguration());
+        newConfig.fontScale = 5;
+        mTask.onRequestedOverrideConfigurationChanged(newConfig);
+
+        mActivity.mRelaunchReason =
+                ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+
+        mActivity.ensureActivityConfiguration(0, false, false);
+
+        assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_NONE,
+                mActivity.mRelaunchReason);
+    }
+
+    @Test
+    public void testSetRequestedOrientationUpdatesConfiguration() throws Exception {
+        mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing");
+
+        mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration());
+        mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(),
+                mActivity.getConfiguration()));
+
+        mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION;
+        final Configuration newConfig = new Configuration(mActivity.getConfiguration());
+        newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT
+                ? Configuration.ORIENTATION_LANDSCAPE
+                : Configuration.ORIENTATION_PORTRAIT;
+
+        // Mimic the behavior that display doesn't handle app's requested orientation.
+        doAnswer(invocation -> {
+            mTask.onConfigurationChanged(newConfig);
+            return null;
+        }).when(mActivity.mAppWindowToken).setOrientation(anyInt(), any(), any());
+
+        final int requestedOrientation;
+        switch (newConfig.orientation) {
+            case Configuration.ORIENTATION_LANDSCAPE:
+                requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+                break;
+            case Configuration.ORIENTATION_PORTRAIT:
+                requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+                break;
+            default:
+                throw new IllegalStateException("Orientation in new config should be either"
+                        + "landscape or portrait.");
+        }
+        mActivity.setRequestedOrientation(requestedOrientation);
+
+        final ActivityConfigurationChangeItem expected =
+                ActivityConfigurationChangeItem.obtain(newConfig);
+        verify(mService.getLifecycleManager()).scheduleTransaction(eq(mActivity.app.getThread()),
+                eq(mActivity.appToken), eq(expected));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index f7b5d26..59e71c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -64,7 +64,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
         mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index b2a2869..35c1ede 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -36,6 +36,8 @@
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -73,7 +75,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
         mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
         mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */));
@@ -264,13 +265,13 @@
 
         // Do not move display to back because there is still another stack.
         stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.topTask());
-        verify(stack2.getWindowContainerController()).positionChildAtBottom(any(),
+        verify(stack2.getTaskStack()).positionChildAtBottom(any(),
                 eq(false) /* includingParents */);
 
         // Also move display to back because there is only one stack left.
         display.removeChild(stack1);
         stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.topTask());
-        verify(stack2.getWindowContainerController()).positionChildAtBottom(any(),
+        verify(stack2.getTaskStack()).positionChildAtBottom(any(),
                 eq(true) /* includingParents */);
     }
 
@@ -687,6 +688,62 @@
     }
 
     @Test
+    public void testHandleAppDied_RelaunchesAfterCrashDuringWindowingModeResize() {
+        final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
+
+        activity.mRelaunchReason = RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+        activity.launchCount = 1;
+        activity.haveState = false;
+
+        mStack.handleAppDiedLocked(activity.app);
+
+        assertEquals(1, mTask.mActivities.size());
+        assertEquals(1, mStack.getAllTasks().size());
+    }
+
+    @Test
+    public void testHandleAppDied_NotRelaunchAfterThreeCrashesDuringWindowingModeResize() {
+        final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
+
+        activity.mRelaunchReason = RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+        activity.launchCount = 3;
+        activity.haveState = false;
+
+        mStack.handleAppDiedLocked(activity.app);
+
+        assertThat(mTask.mActivities).isEmpty();
+        assertThat(mStack.getAllTasks()).isEmpty();
+    }
+
+    @Test
+    public void testHandleAppDied_RelaunchesAfterCrashDuringFreeResize() {
+        final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
+
+        activity.mRelaunchReason = RELAUNCH_REASON_FREE_RESIZE;
+        activity.launchCount = 1;
+        activity.haveState = false;
+
+        mStack.handleAppDiedLocked(activity.app);
+
+        assertEquals(1, mTask.mActivities.size());
+        assertEquals(1, mStack.getAllTasks().size());
+    }
+
+    @Test
+    public void testHandleAppDied_NotRelaunchAfterThreeCrashesDuringFreeResize() {
+        final ActivityRecord activity = new ActivityBuilder(mService).setTask(mTask).build();
+
+        activity.mRelaunchReason = RELAUNCH_REASON_FREE_RESIZE;
+        activity.launchCount = 3;
+        activity.haveState = false;
+
+        mStack.handleAppDiedLocked(activity.app);
+
+        assertThat(mTask.mActivities).isEmpty();
+        assertThat(mStack.getAllTasks()).isEmpty();
+    }
+
+    @Test
     public void testFinishCurrentActivity() {
         // Create 2 activities on a new display.
         final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 2ba2fdb..96db38b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -56,7 +56,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mService = createActivityTaskManagerService();
         mFactory = mock(Factory.class);
         mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory);
         mStarter = spy(new ActivityStarter(mController, mService,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ec88718..a381023 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -117,7 +117,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
         mController = mock(ActivityStartController.class);
         mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
         clearInvocations(mActivityMetricsLogger);
@@ -143,7 +142,7 @@
                 .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
                         WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */))
                 .build();
-        assertThat((Object) task2.getStack()).isInstanceOf(PinnedActivityStack.class);
+        assertThat((Object) task2.getStack()).isInstanceOf(ActivityStack.class);
         mStarter.updateBounds(task2, bounds);
 
         verify(mService, times(1)).resizeStack(eq(task2.getStack().mStackId),
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 5589ca1..68df87e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -39,9 +39,6 @@
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
-
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
@@ -66,11 +63,11 @@
 import android.view.DisplayInfo;
 
 import com.android.internal.app.IVoiceInteractor;
-import com.android.server.appop.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.ServiceThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.PendingIntentController;
+import com.android.server.appop.AppOpsService;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.uri.UriGrantsManagerInternal;
 
@@ -114,6 +111,10 @@
     @Before
     public void setUpBase() {
         mTestInjector.setUp();
+
+        mService = new TestActivityTaskManagerService(mContext);
+        mSupervisor = mService.mStackSupervisor;
+        mRootActivityContainer = mService.mRootActivityContainer;
     }
 
     @After
@@ -125,17 +126,6 @@
         }
     }
 
-    ActivityTaskManagerService createActivityTaskManagerService() {
-        mService = new TestActivityTaskManagerService(mContext);
-        mSupervisor = mService.mStackSupervisor;
-        mRootActivityContainer = mService.mRootActivityContainer;
-        return mService;
-    }
-
-    void setupActivityTaskManagerService() {
-        createActivityTaskManagerService();
-    }
-
     /** Creates a {@link TestActivityDisplay}. */
     TestActivityDisplay createNewActivityDisplay() {
         return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
@@ -377,7 +367,7 @@
                 mStack.addTask(task, true, "creating test task");
                 task.setStack(mStack);
                 task.setTask();
-                mStack.getWindowContainerController().mContainer.addChild(task.mTask, 0);
+                mStack.getTaskStack().addChild(task.mTask, 0);
             }
 
             task.touchActiveTime();
@@ -632,7 +622,7 @@
 
         @SuppressWarnings("TypeParameterUnusedInFormals")
         @Override
-        <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
+        ActivityStack createStackUnchecked(int windowingMode, int activityType,
                 int stackId, boolean onTop) {
             return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this)
                     .setWindowingMode(windowingMode).setActivityType(activityType)
@@ -681,10 +671,9 @@
      * method is called. Note that its functionality depends on the implementations of the
      * construction arguments.
      */
-    protected static class TestActivityStack<T extends StackWindowController>
-            extends ActivityStack<T> {
+    protected static class TestActivityStack
+            extends ActivityStack {
         private int mOnActivityRemovedFromStackCount = 0;
-        private T mContainerController;
 
         static final int IS_TRANSLUCENT_UNSET = 0;
         static final int IS_TRANSLUCENT_FALSE = 1;
@@ -724,20 +713,20 @@
         }
 
         @Override
-        protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
-            mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController();
+        protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
+            mTaskStack = WindowTestUtils.createMockTaskStack();
 
             // Primary pinned stacks require a non-empty out bounds to be set or else all tasks
             // will be moved to the full screen stack.
             if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                 outBounds.set(0, 0, 100, 100);
             }
-            return mContainerController;
+
         }
 
         @Override
-        T getWindowContainerController() {
-            return mContainerController;
+        TaskStack getTaskStack() {
+            return mTaskStack;
         }
 
         void setIsTranslucent(boolean isTranslucent) {
@@ -827,27 +816,23 @@
         }
 
         @SuppressWarnings("TypeParameterUnusedInFormals")
-        <T extends ActivityStack> T build() {
+        ActivityStack build() {
             final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
             if (mWindowingMode == WINDOWING_MODE_PINNED) {
-                return (T) new PinnedActivityStack(mDisplay, stackId,
-                        mRootActivityContainer.mStackSupervisor, mOnTop) {
+                return new ActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor,
+                        mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) {
                     @Override
                     Rect getDefaultPictureInPictureBounds(float aspectRatio) {
                         return new Rect(50, 50, 100, 100);
                     }
 
                     @Override
-                    PinnedStackWindowController createStackWindowController(int displayId,
-                            boolean onTop, Rect outBounds) {
-                        PinnedStackWindowController controller =
-                                mock(PinnedStackWindowController.class);
-                        controller.mContainer = mock(TaskStack.class);
-                        return controller;
+                    void createTaskStack(int displayId, boolean onTop, Rect outBounds) {
+                        mTaskStack = mock(TaskStack.class);
                     }
                 };
             } else {
-                return (T) new TestActivityStack(mDisplay, stackId,
+                return new TestActivityStack(mDisplay, stackId,
                         mRootActivityContainer.mStackSupervisor, mWindowingMode,
                         mActivityType, mOnTop, mCreateActivity);
             }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index fa42289..123de2d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -39,7 +39,9 @@
 
 import androidx.test.filters.SmallTest;
 
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
@@ -52,15 +54,34 @@
 @Presubmit
 public class AppTransitionTests extends WindowTestsBase {
 
+    private static RootWindowContainer sOriginalRootWindowContainer;
+
     private DisplayContent mDc;
 
+    @BeforeClass
+    public static void setUpRootWindowContainerMock() {
+        final WindowManagerService wm = TestSystemServices.getWindowManagerService();
+        // For unit test, we don't need to test performSurfacePlacement to prevent some abnormal
+        // interaction with surfaceflinger native side.
+        sOriginalRootWindowContainer = wm.mRoot;
+        // Creating spied mock of RootWindowContainer shouldn't be done in @Before, since it will
+        // create unnecessary nested spied objects chain, because WindowManagerService object under
+        // test is a single instance shared among all tests that extend WindowTestsBase class.
+        // Instead it should be done once before running all tests in this test class.
+        wm.mRoot = spy(wm.mRoot);
+        doNothing().when(wm.mRoot).performSurfacePlacement(anyBoolean());
+    }
+
+    @AfterClass
+    public static void tearDownRootWindowContainerMock() {
+        final WindowManagerService wm = TestSystemServices.getWindowManagerService();
+        wm.mRoot = sOriginalRootWindowContainer;
+        sOriginalRootWindowContainer = null;
+    }
+
     @Before
     public void setUp() throws Exception {
         mDc = mWm.getDefaultDisplayContentLocked();
-        // For unit test,  we don't need to test performSurfacePlacement to prevent some
-        // abnormal interaction with surfaceflinger native side.
-        mWm.mRoot = spy(mWm.mRoot);
-        doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
     }
 
     @Test
@@ -160,7 +181,7 @@
         assertTrue(dc1.mOpeningApps.size() > 0);
 
         // Move stack to another display.
-        stack1.getController().reparent(dc2.getDisplayId(),  new Rect(), true);
+        stack1.reparent(dc2.getDisplayId(),  new Rect(), true);
 
         // Verify if token are cleared from both pending transition list in former display.
         assertFalse(dc1.mOpeningApps.contains(token1));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3826fac..f399463 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -59,6 +59,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.DisplayMetrics;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -584,15 +585,17 @@
 
     @Test
     public void testOnDescendantOrientationRequestChanged() {
-        final DisplayContent dc = createNewDisplay();
+        final DisplayInfo info = new DisplayInfo();
+        info.logicalWidth = 1080;
+        info.logicalHeight = 1920;
+        info.logicalDensityDpi = 240;
+        final DisplayContent dc = createNewDisplay(info);
+        dc.configureDisplayPolicy();
         mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
-        final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
-                ? SCREEN_ORIENTATION_PORTRAIT
-                : SCREEN_ORIENTATION_LANDSCAPE;
 
         final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
         window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
-        window.mAppToken.setOrientation(newOrientation);
+        window.mAppToken.mOrientation = SCREEN_ORIENTATION_LANDSCAPE;
 
         ActivityRecord activityRecord = mock(ActivityRecord.class);
 
@@ -603,21 +606,22 @@
         verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
                 same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
         final Configuration newDisplayConfig = captor.getValue();
-        assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
+        assertEquals(Configuration.ORIENTATION_LANDSCAPE, newDisplayConfig.orientation);
     }
 
     @Test
     public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
-        final DisplayContent dc = createNewDisplay();
+        final DisplayInfo info = new DisplayInfo();
+        info.logicalWidth = 1080;
+        info.logicalHeight = 1920;
+        info.logicalDensityDpi = 240;
+        final DisplayContent dc = createNewDisplay(info);
         dc.getDisplayRotation().setFixedToUserRotation(true);
         mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
-        final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
-                ? SCREEN_ORIENTATION_PORTRAIT
-                : SCREEN_ORIENTATION_LANDSCAPE;
 
         final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
         window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
-        window.mAppToken.setOrientation(newOrientation);
+        window.mAppToken.mOrientation = SCREEN_ORIENTATION_LANDSCAPE;
 
         ActivityRecord activityRecord = mock(ActivityRecord.class);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 198e7ce..d05711e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -33,7 +33,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.content.ContentResolver;
@@ -612,23 +611,6 @@
     // ========================
     // Non-rotation API Tests
     // ========================
-    @Test
-    public void testRespectsAppRequestedOrientationByDefault() throws Exception {
-        mBuilder.build();
-
-        assertTrue("Display rotation should respect app requested orientation by"
-                + " default.", mTarget.respectAppRequestedOrientation());
-    }
-
-    @Test
-    public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
-        mBuilder.build();
-        mTarget.setFixedToUserRotation(true);
-
-        assertFalse("Display rotation shouldn't respect app requested orientation if"
-                + " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
-    }
-
     /**
      * Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
      * according to given parameters.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index bb3ab35..68d8bc0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -94,8 +94,8 @@
     private WindowState createDropTargetWindow(String name, int ownerId) {
         final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken(
                 mDisplayContent);
-        final TaskStack stack = createStackControllerOnStackOnDisplay(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
+        final TaskStack stack = createTaskStackOnDisplay(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         final Task task = createTaskInStack(stack, ownerId);
         task.addChild(token, 0);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 8c3dec7..b28ae40 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -71,7 +71,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mService = createActivityTaskManagerService();
         mPersister = new TestLaunchParamsPersister();
         mController = new LaunchParamsController(mService, mPersister);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 8635364..aeda473 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -102,8 +102,6 @@
         mFolder = new File(cacheFolder, "launch_params_tests");
         deleteRecursively(mFolder);
 
-        setupActivityTaskManagerService();
-
         mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
         final DisplayInfo info = new DisplayInfo();
         info.uniqueId = mDisplayUniqueId;
diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
index efd7d25..beaac8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java
@@ -52,7 +52,6 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mService = createActivityTaskManagerService();
         mService.mH.runWithScissors(() -> {
             mHandler = new TestHandler(null, mClock);
         }, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 58302d6..e3bacf9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -82,7 +82,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
         mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
     }
@@ -323,8 +322,8 @@
     public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
         // Create stack/task on default display.
         final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
-        final TestActivityStack targetStack =
-                new StackBuilder(mRootActivityContainer).setOnTop(false).build();
+        final TestActivityStack targetStack = (TestActivityStack) new StackBuilder(
+                mRootActivityContainer).setOnTop(false).build();
         final TaskRecord targetTask = targetStack.getChildAt(0);
 
         // Create Recents on top of the display.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index a8b6dc3..dc96480 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -49,7 +49,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
         mRunningTasks = new RunningTasks();
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
deleted file mode 100644
index 5690b58..0000000
--- a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Test class for {@link StackWindowController}.
- *
- * Build/Install/Run:
- *  atest FrameworksServicesTests:StackWindowControllerTests
- */
-@SmallTest
-@Presubmit
-public class StackWindowControllerTests extends WindowTestsBase {
-    @Test
-    public void testRemoveContainer() {
-        final StackWindowController stackController =
-                createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController);
-
-        final TaskStack stack = stackController.mContainer;
-        assertNotNull(stack);
-        assertNotNull(task);
-        stackController.removeContainer();
-        // Assert that the container was removed.
-        assertNull(stackController.mContainer);
-        assertNull(stack.getDisplayContent());
-        assertNull(task.getDisplayContent());
-        assertNull(task.mStack);
-    }
-
-    @Test
-    public void testRemoveContainer_deferRemoval() {
-        final StackWindowController stackController =
-                createStackControllerOnDisplay(mDisplayContent);
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController);
-
-        final TaskStack stack = stackController.mContainer;
-        // Stack removal is deferred if one of its child is animating.
-        task.setLocalIsAnimating(true);
-
-        stackController.removeContainer();
-        // For the case of deferred removal the stack controller will no longer be connected to the
-        // container, but the task controller will still be connected to the its container until
-        // the stack window container is removed.
-        assertNull(stackController.mContainer);
-        assertNull(stack.getController());
-        assertNotNull(task);
-
-        stack.removeImmediately();
-        // After removing, the task will be isolated.
-        assertNull(task.getParent());
-        assertEquals(task.getChildCount(), 0);
-        assertNull(task.getController());
-    }
-
-    @Test
-    public void testReparent() {
-        // Create first stack on primary display.
-        final StackWindowController stack1Controller =
-                createStackControllerOnDisplay(mDisplayContent);
-        final TaskStack stack1 = stack1Controller.mContainer;
-        final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1Controller);
-        task1.mOnDisplayChangedCalled = false;
-
-        // Create second display and put second stack on it.
-        final DisplayContent dc = createNewDisplay();
-        final StackWindowController stack2Controller =
-                createStackControllerOnDisplay(dc);
-        final TaskStack stack2 = stack2Controller.mContainer;
-
-        // Reparent
-        stack1Controller.reparent(dc.getDisplayId(), new Rect(), true /* onTop */);
-        assertEquals(dc, stack1.getDisplayContent());
-        final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
-        final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
-        assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
-        assertTrue(task1.mOnDisplayChangedCalled);
-    }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 53e99fa..ace179a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -75,10 +75,6 @@
 
     @Before
     public void setUp() throws Exception {
-        setupActivityTaskManagerService();
-        mService.mSupportsFreeformWindowManagement = true;
-        when(mSupervisor.canUseActivityOptionsLaunchBounds(any())).thenCallRealMethod();
-
         mActivity = new ActivityBuilder(mService).build();
         mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         mActivity.info.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 8a98cbe..e182c45 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -25,6 +25,13 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.server.wm.WindowContainer.POSITION_TOP;
 
 import static org.hamcrest.Matchers.not;
@@ -46,6 +53,7 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.util.Xml;
 import android.view.DisplayInfo;
+import android.view.Surface;
 
 import androidx.test.filters.MediumTest;
 
@@ -82,7 +90,6 @@
     @Before
     public void setUp() throws Exception {
         TaskRecord.setTaskRecordFactory(null);
-        setupActivityTaskManagerService();
         mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/);
     }
 
@@ -217,12 +224,17 @@
         info.logicalHeight = fullScreenBounds.height();
         ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
         assertTrue(mRootActivityContainer.getActivityDisplay(display.mDisplayId) != null);
+        // Override display orientation. Normally this is available via DisplayContent, but DC
+        // is mocked-out.
+        display.getRequestedOverrideConfiguration().orientation =
+                Configuration.ORIENTATION_LANDSCAPE;
+        display.onRequestedOverrideConfigurationChanged(
+                display.getRequestedOverrideConfiguration());
         ActivityStack stack = new StackBuilder(mRootActivityContainer)
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
         TaskRecord task = stack.getChildAt(0);
-        ActivityRecord root = task.getRootActivity();
-        ActivityRecord top = new ActivityBuilder(mService).setTask(task).setStack(stack).build();
-        assertEquals(root, task.getRootActivity());
+        ActivityRecord root = task.getTopActivity();
+        assertEquals(root, task.getTopActivity());
 
         assertEquals(fullScreenBounds, task.getBounds());
 
@@ -233,16 +245,22 @@
         assertTrue(task.getBounds().width() < task.getBounds().height());
         assertEquals(fullScreenBounds.height(), task.getBounds().height());
 
-        // Setting non-root app has no effect
-        setActivityRequestedOrientation(root, SCREEN_ORIENTATION_LANDSCAPE);
-        assertTrue(task.getBounds().width() < task.getBounds().height());
+        // Top activity gets used
+        ActivityRecord top = new ActivityBuilder(mService).setTask(task).setStack(stack).build();
+        assertEquals(top, task.getTopActivity());
+        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
+        assertTrue(task.getBounds().width() > task.getBounds().height());
+        assertEquals(task.getBounds().width(), fullScreenBounds.width());
 
         // Setting app to unspecified restores
-        setActivityRequestedOrientation(root, SCREEN_ORIENTATION_UNSPECIFIED);
+        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_UNSPECIFIED);
         assertEquals(fullScreenBounds, task.getBounds());
 
         // Setting app to fixed landscape and changing display
-        setActivityRequestedOrientation(root, SCREEN_ORIENTATION_LANDSCAPE);
+        setActivityRequestedOrientation(top, SCREEN_ORIENTATION_LANDSCAPE);
+        // simulate display orientation changing (normally done via DisplayContent)
+        display.getRequestedOverrideConfiguration().orientation =
+                Configuration.ORIENTATION_PORTRAIT;
         display.setBounds(fullScreenBoundsPort);
         assertTrue(task.getBounds().width() > task.getBounds().height());
         assertEquals(fullScreenBoundsPort.width(), task.getBounds().width());
@@ -265,6 +283,51 @@
         assertEquals(freeformBounds, task.getBounds());
     }
 
+    @Test
+    public void testUpdatesForcedOrientationInBackground() {
+        final DisplayInfo info = new DisplayInfo();
+        info.logicalWidth = 1920;
+        info.logicalHeight = 1080;
+        final ActivityDisplay display = addNewActivityDisplayAt(info, POSITION_TOP);
+        doCallRealMethod().when(display.mDisplayContent).setDisplayRotation(any());
+        display.mDisplayContent.setDisplayRotation(mock(DisplayRotation.class));
+        doCallRealMethod().when(display.mDisplayContent).onDescendantOrientationChanged(any(),
+                any());
+        doCallRealMethod().when(display.mDisplayContent).setRotation(anyInt());
+        doAnswer(invocation -> {
+            display.mDisplayContent.setRotation(Surface.ROTATION_0);
+            return null;
+        }).when(display.mDisplayContent).updateOrientationFromAppTokens(any(), any(), anyBoolean());
+
+        final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+                .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
+        final TaskRecord task = stack.getChildAt(0);
+        final ActivityRecord activity = task.getRootActivity();
+
+        // Wire up app window token and task.
+        doCallRealMethod().when(activity.mAppWindowToken).setOrientation(anyInt(), any(), any());
+        doCallRealMethod().when(activity.mAppWindowToken).onDescendantOrientationChanged(any(),
+                any());
+        doReturn(task.mTask).when(activity.mAppWindowToken).getParent();
+
+        // Wire up task and stack.
+        task.mTask.mTaskRecord = task;
+        doCallRealMethod().when(task.mTask).onDescendantOrientationChanged(any(), any());
+        doReturn(stack.getTaskStack()).when(task.mTask).getParent();
+
+        // Wire up stack and display content.
+        doCallRealMethod().when(stack.mTaskStack).onDescendantOrientationChanged(any(), any());
+        doReturn(display.mDisplayContent).when(stack.mTaskStack).getParent();
+
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        assertTrue("Bounds of the task should be pillarboxed.",
+                task.getBounds().width() < task.getBounds().height());
+
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+        assertTrue("Bounds of the task should be fullscreen.",
+                task.getBounds().equals(new Rect(0, 0, 1920, 1080)));
+    }
+
     /** Ensures that the alias intent won't have target component resolved. */
     @Test
     public void testTaskIntentActivityAlias() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index f01e9f0..74ccccc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -47,8 +47,8 @@
 
     @Before
     public void setUp() throws Exception {
-        mPinnedStack = createStackControllerOnStackOnDisplay(
-                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
+        mPinnedStack = createTaskStackOnDisplay(
+                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         // Stack should contain visible app window to be considered visible.
         final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
         assertFalse(mPinnedStack.isVisible());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 7ac3318..2554237 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -20,8 +20,12 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -106,4 +110,62 @@
         assertNull(stack.getDisplayContent());
         assertNull(task.mStack);
     }
+
+    @Test
+    public void testRemoveContainer() {
+        final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack);
+
+        assertNotNull(stack);
+        assertNotNull(task);
+        stack.removeIfPossible();
+        // Assert that the container was removed.
+        assertNull(stack.getParent());
+        assertEquals(0, stack.getChildCount());
+        assertNull(stack.getDisplayContent());
+        assertNull(task.getDisplayContent());
+        assertNull(task.mStack);
+    }
+
+    @Test
+    public void testRemoveContainer_deferRemoval() {
+        final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack);
+
+        // Stack removal is deferred if one of its child is animating.
+        task.setLocalIsAnimating(true);
+
+        stack.removeIfPossible();
+        // For the case of deferred removal the task controller will still be connected to the its
+        // container until the stack window container is removed.
+        assertNotNull(stack.getParent());
+        assertNotEquals(0, stack.getChildCount());
+        assertNotNull(task);
+
+        stack.removeImmediately();
+        // After removing, the task will be isolated.
+        assertNull(task.getParent());
+        assertEquals(0, task.getChildCount());
+        assertNull(task.getController());
+    }
+
+    @Test
+    public void testReparent() {
+        // Create first stack on primary display.
+        final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1);
+        task1.mOnDisplayChangedCalled = false;
+
+        // Create second display and put second stack on it.
+        final DisplayContent dc = createNewDisplay();
+        final TaskStack stack2 = createTaskStackOnDisplay(dc);
+
+        // Reparent
+        stack1.reparent(dc.getDisplayId(), new Rect(), true /* onTop */);
+        assertEquals(dc, stack1.getDisplayContent());
+        final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
+        final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
+        assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
+        assertTrue(task1.mOnDisplayChangedCalled);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 3e32ed3..ae211d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -40,8 +40,7 @@
 
     @Test
     public void testRemoveContainer() {
-        final StackWindowController stackController1 =
-                createStackControllerOnDisplay(mDisplayContent);
+        final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
         final WindowTestUtils.TestAppWindowToken appToken =
                 WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
@@ -49,14 +48,13 @@
         task.removeIfPossible();
         // Assert that the container was removed.
         assertNull(task.getParent());
-        assertEquals(task.getChildCount(), 0);
+        assertEquals(0, task.getChildCount());
         assertNull(appToken.getParent());
     }
 
     @Test
     public void testRemoveContainer_deferRemoval() {
-        final StackWindowController stackController1 =
-                createStackControllerOnDisplay(mDisplayContent);
+        final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
         final WindowTestUtils.TestAppWindowToken appToken =
                 WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task);
@@ -67,22 +65,20 @@
         // For the case of deferred removal the task will still be connected to the its app token
         // until the task window container is removed.
         assertNotNull(task.getParent());
-        assertNotEquals(task.getChildCount(), 0);
+        assertNotEquals(0, task.getChildCount());
         assertNotNull(appToken.getParent());
 
         task.removeImmediately();
         assertNull(task.getParent());
-        assertEquals(task.getChildCount(), 0);
+        assertEquals(0, task.getChildCount());
         assertNull(appToken.getParent());
     }
 
     @Test
     public void testReparent() {
-        final StackWindowController stackController1 =
-                createStackControllerOnDisplay(mDisplayContent);
+        final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1);
-        final StackWindowController stackController2 =
-                createStackControllerOnDisplay(mDisplayContent);
+        final TaskStack stackController2 = createTaskStackOnDisplay(mDisplayContent);
         final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stackController2);
 
         boolean gotException = false;
@@ -93,20 +89,17 @@
         }
         assertTrue("Should not be able to reparent to the same parent", gotException);
 
-        final StackWindowController stackController3 =
-                createStackControllerOnDisplay(mDisplayContent);
-        stackController3.setContainer(null);
         gotException = false;
         try {
-            task.reparent(stackController3, 0, false/* moveParents */);
+            task.reparent(null, 0, false/* moveParents */);
         } catch (IllegalArgumentException e) {
             gotException = true;
         }
-        assertTrue("Should not be able to reparent to a stack that doesn't have a container",
+        assertTrue("Should not be able to reparent to a stack that doesn't exist",
                 gotException);
 
         task.reparent(stackController2, 0, false/* moveParents */);
-        assertEquals(stackController2.mContainer, task.getParent());
+        assertEquals(stackController2, task.getParent());
         assertEquals(0, task.positionInParent());
         assertEquals(1, task2.positionInParent());
     }
@@ -114,20 +107,17 @@
     @Test
     public void testReparent_BetweenDisplays() {
         // Create first stack on primary display.
-        final StackWindowController stack1Controller =
-                createStackControllerOnDisplay(mDisplayContent);
-        final TaskStack stack1 = stack1Controller.mContainer;
-        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1Controller);
+        final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent);
+        final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1);
         task.mOnDisplayChangedCalled = false;
         assertEquals(mDisplayContent, stack1.getDisplayContent());
 
         // Create second display and put second stack on it.
         final DisplayContent dc = createNewDisplay();
-        final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
-        final TaskStack stack2 = stack2Controller.mContainer;
-        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2Controller);
+        final TaskStack stack2 = createTaskStackOnDisplay(dc);
+        final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2);
         // Reparent and check state
-        task.reparent(stack2Controller, 0, false /* moveParents */);
+        task.reparent(stack2, 0, false /* moveParents */);
         assertEquals(stack2, task.getParent());
         assertEquals(0, task.positionInParent());
         assertEquals(1, task2.positionInParent());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
similarity index 97%
rename from services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java
rename to services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
index 05ac8c1..b151fb7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java
@@ -66,7 +66,7 @@
 /**
  * A Test utility class to create a mock {@link WindowManagerService} instance for tests.
  */
-class WmServiceUtils {
+class TestSystemServices {
     private static StaticMockitoSession sMockitoSession;
     private static WindowManagerService sService;
     private static TestWindowManagerPolicy sPolicy;
@@ -78,7 +78,7 @@
                 .strictness(Strictness.LENIENT)
                 .startMocking();
 
-        runWithDexmakerShareClassLoader(WmServiceUtils::setUpTestWindowService);
+        runWithDexmakerShareClassLoader(TestSystemServices::setUpTestWindowService);
     }
 
     static void tearDownWindowManagerService() {
@@ -147,7 +147,7 @@
         final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock();
         doReturn(wmLock).when(atms).getGlobalLock();
 
-        sPolicy = new TestWindowManagerPolicy(WmServiceUtils::getWindowManagerService);
+        sPolicy = new TestWindowManagerPolicy(TestSystemServices::getWindowManagerService);
         sService = WindowManagerService.main(context, ims, false, false, sPolicy, atms);
 
         sService.onInitReady();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index d9ef10d..0a4a8a4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -16,12 +16,15 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
 import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
 
 import android.app.ActivityManager.TaskDescription;
 import android.content.res.Configuration;
@@ -58,7 +61,7 @@
         boolean mDockedResizingForTest = false;
         WindowStateWithTask(WindowManagerService wm, IWindow iWindow, WindowToken windowToken,
                 WindowManager.LayoutParams attrs, Task t) {
-            super(wm, null, iWindow, windowToken, null, 0, 0, attrs, 0, 0,
+            super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0,
                     false /* ownerCanAddInternalSystemWindow */);
             mTask = t;
         }
@@ -113,9 +116,9 @@
 
     @Before
     public void setUp() throws Exception {
-        mWindowToken = WindowTestUtils.createTestAppWindowToken(
-                mWm.getDefaultDisplayContentLocked());
-        mStubStack = new TaskStack(mWm, 0, null);
+        mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(),
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        mStubStack = WindowTestUtils.createMockTaskStack();
     }
 
     // Do not use this function directly in the tests below. Instead, use more explicit function
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 20fc5ae..44e998b7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -103,12 +103,10 @@
     }
 
     /**
-     * Creates a mock instance of {@link StackWindowController}.
+     * Creates a mock instance of {@link TestTaskStack}.
      */
-    public static StackWindowController createMockStackWindowContainerController() {
-        StackWindowController controller = mock(StackWindowController.class);
-        controller.mContainer = mock(TestTaskStack.class);
-        return controller;
+    public static TaskStack createMockTaskStack() {
+        return mock(TestTaskStack.class);
     }
 
     /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
@@ -201,6 +199,11 @@
         }
 
         @Override
+        void onParentSet() {
+            // Do nothing.
+        }
+
+        @Override
         boolean isOnTop() {
             return mOnTop;
         }
@@ -283,10 +286,9 @@
         }
     }
 
-    public static TestTask createTestTask(StackWindowController stackWindowController) {
-        return new TestTask(sNextTaskId++, stackWindowController.mContainer, 0,
-                stackWindowController.mService, RESIZE_MODE_UNRESIZEABLE, false,
-                mock(TaskRecord.class));
+    public static TestTask createTestTask(TaskStack stack) {
+        return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE,
+                false, mock(TaskRecord.class));
     }
 
     public static class TestIApplicationToken implements IApplicationToken {
@@ -334,5 +336,10 @@
 
             mHasSurface = hadSurface;
         }
+
+        @Override
+        void onParentSet() {
+            // Do nothing;
+        }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index cdc0a47..e38118e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -41,7 +41,6 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Rect;
 import android.hardware.display.DisplayManagerGlobal;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.util.Log;
@@ -102,14 +101,14 @@
     public static void setUpOnceBase() {
         AttributeCache.init(getInstrumentation().getTargetContext());
 
-        WmServiceUtils.setUpWindowManagerService();
+        TestSystemServices.setUpWindowManagerService();
 
         sPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
     }
 
     @AfterClass
     public static void tearDonwOnceBase() {
-        WmServiceUtils.tearDownWindowManagerService();
+        TestSystemServices.tearDownWindowManagerService();
     }
 
     @Before
@@ -121,7 +120,7 @@
 
             final Context context = getInstrumentation().getTargetContext();
 
-            mWm = WmServiceUtils.getWindowManagerService();
+            mWm = TestSystemServices.getWindowManagerService();
             beforeCreateDisplay();
 
             context.getDisplay().getDisplayInfo(mDisplayInfo);
@@ -199,7 +198,7 @@
             }
 
             // Cleaned up everything in Handler.
-            WmServiceUtils.cleanupWindowManagerHandlers();
+            TestSystemServices.cleanupWindowManagerHandlers();
         } catch (Exception e) {
             Log.e(TAG, "Failed to tear down test", e);
             throw e;
@@ -220,7 +219,7 @@
      * Waits until the main handler for WM has processed all messages.
      */
     void waitUntilHandlersIdle() {
-        WmServiceUtils.waitUntilWindowManagerHandlersIdle();
+        TestSystemServices.waitUntilWindowManagerHandlersIdle();
     }
 
     private WindowToken createWindowToken(
@@ -240,8 +239,7 @@
 
     WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int
             windowingMode, int activityType) {
-        final TaskStack stack = createStackControllerOnStackOnDisplay(windowingMode, activityType,
-                dc).mContainer;
+        final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
         final Task task = createTaskInStack(stack, 0 /* userId */);
         final WindowTestUtils.TestAppWindowToken appWindowToken =
                 WindowTestUtils.createTestAppWindowToken(dc);
@@ -350,28 +348,20 @@
     /** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */
     TaskStack createTaskStackOnDisplay(DisplayContent dc) {
         synchronized (mWm.mGlobalLock) {
-            return createStackControllerOnDisplay(dc).mContainer;
+            return createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc);
         }
     }
 
-    StackWindowController createStackControllerOnDisplay(DisplayContent dc) {
-        synchronized (mWm.mGlobalLock) {
-            return createStackControllerOnStackOnDisplay(
-                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc);
-        }
-    }
-
-    StackWindowController createStackControllerOnStackOnDisplay(
-            int windowingMode, int activityType, DisplayContent dc) {
+    TaskStack createTaskStackOnDisplay(int windowingMode, int activityType, DisplayContent dc) {
         synchronized (mWm.mGlobalLock) {
             final Configuration overrideConfig = new Configuration();
             overrideConfig.windowConfiguration.setWindowingMode(windowingMode);
             overrideConfig.windowConfiguration.setActivityType(activityType);
             final int stackId = ++sNextStackId;
-            final StackWindowController controller = new StackWindowController(stackId, null,
-                    dc.getDisplayId(), true /* onTop */, new Rect(), mWm);
-            controller.onRequestedOverrideConfigurationChanged(overrideConfig);
-            return controller;
+            final TaskStack stack = new TaskStack(mWm, stackId, mock(ActivityStack.class));
+            dc.setStackOnDisplay(stackId, true, stack);
+            stack.onRequestedOverrideConfigurationChanged(overrideConfig);
+            return stack;
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 94cc650..9a5bd13 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -22,6 +22,7 @@
 import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
 import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
 import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageEvents.Event.END_OF_DAY;
 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
@@ -66,7 +67,7 @@
     public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
     public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
     public Configuration activeConfiguration;
-    public EventList events;
+    public EventList events = new EventList();
 
     // A string cache. This is important as when we're parsing XML files, we don't want to
     // keep hundreds of strings that have the same contents. We will read the string
@@ -112,6 +113,9 @@
 
     }
 
+    public IntervalStats() {
+    }
+
     /**
      * Gets the UsageStats object for the given package, or creates one and adds it internally.
      */
@@ -253,6 +257,7 @@
             case ROLLOVER_FOREGROUND_SERVICE:
             case CONTINUE_PREVIOUS_DAY:
             case CONTINUING_FOREGROUND_SERVICE:
+            case DEVICE_SHUTDOWN:
                 return true;
         }
         return false;
@@ -281,8 +286,9 @@
     @VisibleForTesting
     public void update(String packageName, String className, long timeStamp, int eventType,
             int instanceId) {
-        if (eventType == FLUSH_TO_DISK) {
-            // FLUSH_TO_DISK are sent to all packages.
+        if (eventType == DEVICE_SHUTDOWN
+                || eventType == FLUSH_TO_DISK) {
+            // DEVICE_SHUTDOWN and FLUSH_TO_DISK are sent to all packages.
             final int size = packageStats.size();
             for (int i = 0; i < size; i++) {
                 UsageStats usageStats = packageStats.valueAt(i);
@@ -321,9 +327,6 @@
      */
     @VisibleForTesting
     public void addEvent(Event event) {
-        if (events == null) {
-            events = new EventList();
-        }
         // Cache common use strings
         event.mPackage = getCachedStringRef(event.mPackage);
         if (event.mClass != null) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index f146370..76a3aa8 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -18,6 +18,7 @@
 
 import static android.app.usage.UsageEvents.Event.CHOOSER_ACTION;
 import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
+import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
 import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
@@ -416,11 +417,30 @@
      */
     void shutdown() {
         synchronized (mLock) {
+            mHandler.removeMessages(MSG_REPORT_EVENT);
+            Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
+            // orderly shutdown, the last event is DEVICE_SHUTDOWN.
+            reportEventToAllUserId(event);
             flushToDiskLocked();
         }
     }
 
     /**
+     * After power button is pressed for 3.5 seconds
+     * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}),
+     * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10
+     * seconds and the device is shutdown, the database is already persisted and we are not losing
+     * data.
+     * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise
+     * PhoneWindowManager may be blocked.
+     */
+    void prepareForPossibleShutdown() {
+        Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
+        mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget();
+        mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK);
+    }
+
+    /**
      * Called by the Binder stub.
      */
     void reportEvent(Event event, int userId) {
@@ -1487,6 +1507,11 @@
         }
 
         @Override
+        public void prepareForPossibleShutdown() {
+            UsageStatsService.this.prepareForPossibleShutdown();
+        }
+
+        @Override
         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
             mAppStandby.addListener(listener);
             listener.onParoleStateChanged(isAppIdleParoleOn());
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 5128ae1..2d1098c7 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
 import static android.app.usage.UsageStatsManager.INTERVAL_BEST;
 import static android.app.usage.UsageStatsManager.INTERVAL_COUNT;
 import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
@@ -134,6 +135,18 @@
             updateRolloverDeadline();
         }
 
+        // During system reboot, add a DEVICE_SHUTDOWN event to the end of event list, the timestamp
+        // is last time UsageStatsDatabase is persisted to disk.
+        final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
+        if (currentDailyStats != null) {
+            final int size = currentDailyStats.events.size();
+            if (size == 0 || currentDailyStats.events.get(size - 1).mEventType != DEVICE_SHUTDOWN) {
+                // The last event in event list is not DEVICE_SHUTDOWN, then we insert one.
+                final Event event = new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved);
+                currentDailyStats.addEvent(event);
+            }
+        }
+
         if (mDatabase.isNewUpdate()) {
             notifyNewUpdate();
         }
@@ -175,7 +188,9 @@
                 // ACTIVITY_STOPPED.
                 && event.mEventType != Event.ACTIVITY_DESTROYED
                 // FLUSH_TO_DISK is a private event.
-                && event.mEventType != Event.FLUSH_TO_DISK) {
+                && event.mEventType != Event.FLUSH_TO_DISK
+                // DEVICE_SHUTDOWN is added to event list after reboot.
+                && event.mEventType != Event.DEVICE_SHUTDOWN) {
             currentDailyStats.addEvent(event);
         }
 
@@ -393,10 +408,6 @@
                     @Override
                     public void combine(IntervalStats stats, boolean mutable,
                             List<Event> accumulatedResult) {
-                        if (stats.events == null) {
-                            return;
-                        }
-
                         final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                         final int size = stats.events.size();
                         for (int i = startIndex; i < size; i++) {
@@ -434,10 +445,6 @@
         names.add(packageName);
         final List<Event> results = queryStats(INTERVAL_DAILY,
                 beginTime, endTime, (stats, mutable, accumulatedResult) -> {
-                    if (stats.events == null) {
-                        return;
-                    }
-
                     final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                     final int size = stats.events.size();
                     for (int i = startIndex; i < size; i++) {
@@ -696,10 +703,6 @@
                     @Override
                     public void combine(IntervalStats stats, boolean mutable,
                             List<Event> accumulatedResult) {
-                        if (stats.events == null) {
-                            return;
-                        }
-
                         final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                         final int size = stats.events.size();
                         for (int i = startIndex; i < size; i++) {
@@ -925,10 +928,12 @@
                 return "SCREEN_INTERACTIVE";
             case Event.SCREEN_NON_INTERACTIVE:
                 return "SCREEN_NON_INTERACTIVE";
-            case UsageEvents.Event.KEYGUARD_SHOWN:
+            case Event.KEYGUARD_SHOWN:
                 return "KEYGUARD_SHOWN";
-            case UsageEvents.Event.KEYGUARD_HIDDEN:
+            case Event.KEYGUARD_HIDDEN:
                 return "KEYGUARD_HIDDEN";
+            case Event.DEVICE_SHUTDOWN:
+                return "DEVICE_SHUTDOWN";
             default:
                 return "UNKNOWN_TYPE_" + eventType;
         }
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index bbf3d45..613c4ff 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -371,14 +371,15 @@
         }
 
         private boolean shouldEnableService(Context context) {
-            // VoiceInteractionService should not be enabled on any low RAM devices
-            // or devices that have not declared the recognition feature, unless the
-            // device's configuration has explicitly set the config flag for a fixed
+            // VoiceInteractionService should not be enabled on devices that have not declared the
+            // recognition feature (including low-ram devices where notLowRam="true" takes effect),
+            // unless the device's configuration has explicitly set the config flag for a fixed
             // voice interaction service.
-            return (!ActivityManager.isLowRamDeviceStatic()
-                            && context.getPackageManager().hasSystemFeature(
-                                    PackageManager.FEATURE_VOICE_RECOGNIZERS)) ||
-                    getForceVoiceInteractionServicePackage(context.getResources()) != null;
+            if (getForceVoiceInteractionServicePackage(context.getResources()) != null) {
+                return true;
+            }
+            return context.getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_VOICE_RECOGNIZERS);
         }
 
         private String getForceVoiceInteractionServicePackage(Resources res) {
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index fe07370..4da79b3 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -110,6 +110,7 @@
     private AvailableNetworkInfo(Parcel in) {
         mSubId = in.readInt();
         mPriority = in.readInt();
+        mMccMncs = new ArrayList<>();
         in.readStringList(mMccMncs);
     }
 
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
index 35769f0..eafbfbc 100644
--- a/telephony/java/android/telephony/CellConfigLte.java
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -34,6 +34,11 @@
     }
 
     /** @hide */
+    public CellConfigLte(android.hardware.radio.V1_4.CellConfigLte cellConfig) {
+        mIsEndcAvailable = cellConfig.isEndcAvailable;
+    }
+
+    /** @hide */
     public CellConfigLte(boolean isEndcAvailable) {
         mIsEndcAvailable = isEndcAvailable;
     }
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index b761bd7..8ce5c54 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -19,8 +19,10 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
+import android.hardware.radio.V1_4.CellInfo.Info;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -318,6 +320,13 @@
     }
 
     /** @hide */
+    protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) {
+        this.mRegistered = ci.isRegistered;
+        this.mTimeStamp = SystemClock.elapsedRealtimeNanos();
+        this.mCellConnectionStatus = ci.connectionStatus;
+    }
+
+    /** @hide */
     public static CellInfo create(android.hardware.radio.V1_0.CellInfo ci) {
         if (ci == null) return null;
         switch(ci.cellInfoType) {
@@ -342,4 +351,17 @@
             default: return null;
         }
     }
+
+    /** @hide */
+    public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) {
+        if (ci == null) return null;
+        switch (ci.info.getDiscriminator()) {
+            case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci);
+            case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci);
+            case Info.hidl_discriminator.lte: return new CellInfoLte(ci);
+            case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci);
+            case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci);
+            default: return null;
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index c9f07da..4440108 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -67,6 +67,15 @@
             new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
     }
 
+    /** @hide */
+    public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) {
+        super(ci);
+        final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma();
+        mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
+        mCellSignalStrengthCdma =
+                new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
+    }
+
     @Override
     public CellIdentityCdma getCellIdentity() {
         return mCellIdentityCdma;
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index ad16dfa..248adfc 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -63,6 +63,14 @@
         mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
     }
 
+    /** @hide */
+    public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) {
+        super(ci);
+        final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm();
+        mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
+        mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
+    }
+
     @Override
     public CellIdentityGsm getCellIdentity() {
         return mCellIdentityGsm;
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 7593831..8e8ce8a 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -70,6 +70,15 @@
         mCellConfig = new CellConfigLte();
     }
 
+    /** @hide */
+    public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) {
+        super(ci);
+        final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte();
+        mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte);
+        mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte);
+        mCellConfig = new CellConfigLte(cil.cellConfig);
+    }
+
     @Override
     public CellIdentityLte getCellIdentity() {
         if (DBG) log("getCellIdentity: " + mCellIdentityLte);
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index a8c49b7..2ab38fb 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -64,6 +64,14 @@
         mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
     }
 
+    /** @hide */
+    public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) {
+        super(ci);
+        final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma();
+        mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
+        mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
+    }
+
     @Override public CellIdentityTdscdma getCellIdentity() {
         return mCellIdentityTdscdma;
     }
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index a427e80..65e0470 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -63,6 +63,14 @@
         mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
     }
 
+    /** @hide */
+    public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) {
+        super(ci);
+        final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma();
+        mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
+        mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
+    }
+
     @Override
     public CellIdentityWcdma getCellIdentity() {
         return mCellIdentityWcdma;
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index c816701..9fee593 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -805,9 +805,11 @@
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
 
-            Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(
-                            () -> psl.onDataConnectionStateChanged(state, networkType)));
+            Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+                    () -> {
+                        psl.onDataConnectionStateChanged(state, networkType);
+                        psl.onDataConnectionStateChanged(state);
+                    }));
         }
 
         public void onDataActivity(int direction) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index babeb7b..3311218 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -9963,7 +9963,7 @@
         boolean ret = false;
         try {
             IOns iOpportunisticNetworkService = getIOns();
-            if (iOpportunisticNetworkService != null) {
+            if (iOpportunisticNetworkService != null && availableNetworks != null) {
                 ret = iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks,
                         pkgForDebug);
             }
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index a5f56bb..e68256d 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -27,6 +27,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -176,6 +177,12 @@
      * Bit-field which indicates the number is from the platform-maintained database.
      */
     public static final int EMERGENCY_NUMBER_SOURCE_DATABASE =  1 << 4;
+    /**
+     * Bit-field which indicates the number is from test mode.
+     *
+     * @hide
+     */
+    public static final int EMERGENCY_NUMBER_SOURCE_TEST =  1 << 5;
     /** Bit-field which indicates the number is from the modem config. */
     public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG =
             EmergencyNumberSource.MODEM_CONFIG;
@@ -327,6 +334,21 @@
     }
 
     /**
+     * Returns the bitmask of emergency service categories of the emergency number for
+     * internal dialing.
+     *
+     * @return bitmask of the emergency service categories
+     *
+     * @hide
+     */
+    public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmaskInternalDial() {
+        if (mEmergencyNumberSourceBitmask == EMERGENCY_NUMBER_SOURCE_DATABASE) {
+            return EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+        }
+        return mEmergencyServiceCategoryBitmask;
+    }
+
+    /**
      * Returns the emergency service categories of the emergency number.
      *
      * Note: if the emergency number is in {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}, only
@@ -577,6 +599,7 @@
                 emergencyNumberList.remove(i--);
             }
         }
+        Collections.sort(emergencyNumberList);
     }
 
     /**
@@ -613,6 +636,12 @@
         if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) {
             return false;
         }
+        // Never merge two numbers if one of them is from test mode but the other one is not;
+        // This supports to remove a number from the test mode.
+        if (first.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST)
+                ^ second.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST)) {
+            return false;
+        }
         return true;
     }
 
@@ -638,4 +667,13 @@
         }
         return null;
     }
+
+    /**
+     * Validate Emergency Number address that only allows '0'-'9', '*', or '#'
+     *
+     * @hide
+     */
+    public static boolean validateEmergencyNumberAddress(String address) {
+        return address.matches("[0-9*#]+");
+    }
 }
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 525a96a..59167b7 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -347,6 +347,9 @@
     private @EmergencyCallRouting int mEmergencyCallRouting =
             EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
 
+    /** Indicates if the call is for testing purpose */
+    private boolean mEmergencyCallTesting = false;
+
     /**
      * Extras associated with this {@link ImsCallProfile}.
      * <p>
@@ -534,9 +537,10 @@
                 + ", callType=" + mCallType
                 + ", restrictCause=" + mRestrictCause
                 + ", mediaProfile=" + mMediaProfile.toString()
-                + ", emergencyServiceCategories=" + mEmergencyCallRouting
+                + ", emergencyServiceCategories=" + mEmergencyServiceCategories
                 + ", emergencyUrns=" + mEmergencyUrns
-                + ", emergencyCallRouting=" + mEmergencyCallRouting + " }";
+                + ", emergencyCallRouting=" + mEmergencyCallRouting
+                + ", emergencyCallTesting=" + mEmergencyCallTesting + " }";
     }
 
     @Override
@@ -554,6 +558,7 @@
         out.writeInt(mEmergencyServiceCategories);
         out.writeStringList(mEmergencyUrns);
         out.writeInt(mEmergencyCallRouting);
+        out.writeBoolean(mEmergencyCallTesting);
     }
 
     private void readFromParcel(Parcel in) {
@@ -564,6 +569,7 @@
         mEmergencyServiceCategories = in.readInt();
         mEmergencyUrns = in.createStringArrayList();
         mEmergencyCallRouting = in.readInt();
+        mEmergencyCallTesting = in.readBoolean();
     }
 
     public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
@@ -784,9 +790,11 @@
      * @hide
      */
     public void setEmergencyCallInfo(EmergencyNumber num) {
-        setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmask());
+        setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial());
         setEmergencyUrns(num.getEmergencyUrns());
         setEmergencyCallRouting(num.getEmergencyCallRouting());
+        setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask()
+                == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST);
     }
 
     /**
@@ -843,6 +851,15 @@
     }
 
     /**
+     * Set if this is for testing emergency call, only valid if {@link #getServiceType} returns
+     * {@link #SERVICE_TYPE_EMERGENCY}.
+     */
+    @VisibleForTesting
+    public void setEmergencyCallTesting(boolean isTesting) {
+        mEmergencyCallTesting = isTesting;
+    }
+
+    /**
      * Get the emergency service categories, only valid if {@link #getServiceType} returns
      * {@link #SERVICE_TYPE_EMERGENCY}
      *
@@ -892,4 +909,11 @@
     public @EmergencyCallRouting int getEmergencyCallRouting() {
         return mEmergencyCallRouting;
     }
+
+    /**
+     * Get if the emergency call is for testing purpose.
+     */
+    public boolean isEmergencyCallTesting() {
+        return mEmergencyCallTesting;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index e2350fe..9414abd 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -92,7 +92,7 @@
     public static final int WIFI_MODE_WIFI_PREFERRED = 2;
 
     /**
-     * Callback class for receiving Registration callback events.
+     * Callback class for receiving IMS network Registration callback events.
      * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
      * @see #unregisterImsRegistrationCallback(RegistrationCallback)
      */
@@ -241,7 +241,8 @@
     }
 
     /**
-     * Receives IMS capability status updates from the ImsService.
+     * Receives IMS capability status updates from the ImsService. This information is also
+     * available via the {@link #isAvailable(int, int)} method below.
      *
      * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
      * @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
@@ -290,6 +291,8 @@
          * If unavailable, the feature is not able to support the unavailable capability at this
          * time.
          *
+         * This information can also be queried using the {@link #isAvailable(int, int)} API.
+         *
          * @param capabilities The new availability of the capabilities.
          */
         public void onCapabilitiesStatusChanged(
@@ -304,7 +307,7 @@
         /**@hide*/
         // Only exposed as public method for compatibility with deprecated ImsManager APIs.
         // TODO: clean up dependencies and change back to private visibility.
-        public void setExecutor(Executor executor) {
+        public final void setExecutor(Executor executor) {
             mBinder.setExecutor(executor);
         }
     }
@@ -342,8 +345,7 @@
      * Registers a {@link RegistrationCallback} with the system, which will provide registration
      * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use
      * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
-     * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up
-     * after a subscription is removed.
+     * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
      *
      * When the callback is registered, it will initiate the callback c to be called with the
      * current registration state.
@@ -351,6 +353,12 @@
      * @param executor The executor the callback events should be run on.
      * @param c The {@link RegistrationCallback} to be added.
      * @see #unregisterImsRegistrationCallback(RegistrationCallback)
+     * @throws IllegalArgumentException if the subscription associated with this callback is not
+     * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+     * {@link CapabilityCallback} callback.
+     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * the {@link ImsService} associated with the subscription is not available. This can happen if
+     * the service crashed, for example.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerImsRegistrationCallback(@CallbackExecutor Executor executor,
@@ -370,11 +378,17 @@
     }
 
     /**
-     * Removes an existing {@link RegistrationCallback}. Ensure to call this method when cleaning
-     * up to avoid memory leaks or when the subscription is removed.
+     * Removes an existing {@link RegistrationCallback}.
+     *
+     * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+     * etc...), this callback will automatically be removed. If this method is called for an
+     * inactive subscription, it will result in a no-op.
+     *
      * @param c The {@link RegistrationCallback} to be removed.
      * @see SubscriptionManager.OnSubscriptionsChangedListener
      * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+     * @throws IllegalArgumentException if the subscription ID associated with this callback is
+     * invalid.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
@@ -389,12 +403,14 @@
     }
 
     /**
-     * Registers a {@link CapabilityCallback} with the system, which will provide MmTel capability
-     * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}.
+     * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
+     * availability updates for the subscription specified in
+     * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)}
+     * can also be used to query this information at any time.
+     *
      * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
      * subscription changed events and call
-     * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up after a
-     * subscription is removed.
+     * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
      *
      * When the callback is registered, it will initiate the callback c to be called with the
      * current capabilities.
@@ -402,9 +418,15 @@
      * @param executor The executor the callback events should be run on.
      * @param c The MmTel {@link CapabilityCallback} to be registered.
      * @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
+     * @throws IllegalArgumentException if the subscription associated with this callback is not
+     * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+     * {@link CapabilityCallback} callback.
+     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * the {@link ImsService} associated with the subscription is not available. This can happen if
+     * the service crashed, for example.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void registerMmTelCapabilityCallback(@CallbackExecutor Executor executor,
+    public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull CapabilityCallback c) {
         if (c == null) {
             throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -421,10 +443,15 @@
     }
 
     /**
-     * Removes an existing MmTel {@link CapabilityCallback}. Be sure to call this when cleaning
-     * up to avoid memory leaks.
+     * Removes an existing MmTel {@link CapabilityCallback}.
+     *
+     * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+     * etc...), this callback will automatically be removed. If this method is called for an
+     * inactive subscription, it will result in a no-op.
      * @param c The MmTel {@link CapabilityCallback} to be removed.
      * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback)
+     * @throws IllegalArgumentException if the subscription ID associated with this callback is
+     * invalid.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) {
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 916e282..d37198a 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -133,33 +133,40 @@
     }
 
     /**
-     * Register a new {@link Callback} to listen to changes to changes in
-     * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
-     * Subscription changed events and call
-     * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
-     * subscription is removed.
+     * Register a new {@link Callback} to listen to changes to changes in IMS provisioning.
+     *
+     * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+     * etc...), this callback will automatically be removed.
      * @param executor The {@link Executor} to call the callback methods on
      * @param callback The provisioning callbackto be registered.
      * @see #unregisterProvisioningChangedCallback(Callback)
      * @see SubscriptionManager.OnSubscriptionsChangedListener
+     * @throws IllegalArgumentException if the subscription associated with this callback is not
+     * active (SIM is not inserted, ESIM inactive) or the subscription is invalid.
+     * @throws IllegalStateException if the subscription associated with this callback is valid, but
+     * the {@link ImsService} associated with the subscription is not available. This can happen if
+     * the service crashed, for example.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
             @NonNull Callback callback) {
         callback.setExecutor(executor);
         try {
-            getITelephony().registerImsProvisioningChangedCallback(mSubId,
-                    callback.getBinder());
+            getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
     }
 
     /**
-     * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
-     * up to avoid memory leaks or when the subscription is removed.
+     * Unregister an existing {@link Callback}. When the subscription associated with this
+     * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
+     * removed. If this method is called for an inactive subscription, it will result in a no-op.
      * @param callback The existing {@link Callback} to be removed.
      * @see #registerProvisioningChangedCallback(Executor, Callback)
+     *
+     * @throws IllegalArgumentException if the subscription associated with this callback is
+     * invalid.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 96f7a1b..17516bc2 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -66,7 +66,8 @@
     public static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
     public static final int EVENT_ROAMING_ON = BASE + 11;
     public static final int EVENT_ROAMING_OFF = BASE + 12;
-    public static final int EVENT_ENABLE_NEW_APN = BASE + 13;
+    public static final int EVENT_ENABLE_APN = BASE + 13;
+    public static final int EVENT_DISABLE_APN = BASE + 14;
     public static final int EVENT_DISCONNECT_DONE = BASE + 15;
     public static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
     public static final int EVENT_DATA_STALL_ALARM = BASE + 17;
@@ -92,6 +93,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_PROVISIONED_CHANGE = BASE + 50;
 
     /***** Constants *****/
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c5d82c5..f8e4adc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -41,6 +41,7 @@
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyHistogram;
 import android.telephony.VisualVoicemailSmsFilterSettings;
+import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsConfigCallback;
@@ -1776,4 +1777,14 @@
      * Set the String provisioning value for the provisioning key specified.
      */
     int setImsProvisioningString(int subId, int key, String value);
+
+    /**
+     * Update Emergency Number List for Test Mode.
+     */
+    void updateEmergencyNumberListTestMode(int action, in EmergencyNumber num);
+
+    /**
+     * Get the full emergency number list for Test Mode.
+     */
+    List<String> getEmergencyNumberListTestMode();
 }
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 2a648bd..8523554 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -501,4 +501,18 @@
      */
     public static final String ACTION_LINE1_NUMBER_ERROR_DETECTED =
             "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED";
+
+    /**
+     * Broadcast action to notify radio bug.
+     *
+     * Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * @hide
+     */
+    public static final String ACTION_REPORT_RADIO_BUG =
+            "com.android.internal.telephony.ACTION_REPORT_RADIO_BUG";
+
+    // ACTION_REPORT_RADIO_BUG extra keys
+    public static final String EXTRA_SLOT_ID = "slotId";
+    public static final String EXTRA_RADIO_BUG_TYPE = "radioBugType";
 }
diff --git a/test-base/api/current.txt b/test-base/api/current.txt
index 7ebd6aa..91fcca5 100644
--- a/test-base/api/current.txt
+++ b/test-base/api/current.txt
@@ -48,6 +48,9 @@
     method public abstract void startTiming(boolean);
   }
 
+  public abstract deprecated class RepetitiveTest implements java.lang.annotation.Annotation {
+  }
+
   public abstract deprecated class UiThreadTest implements java.lang.annotation.Annotation {
   }
 
diff --git a/test-base/src/android/test/RepetitiveTest.java b/test-base/src/android/test/RepetitiveTest.java
index 6a7130e..13e89d2 100644
--- a/test-base/src/android/test/RepetitiveTest.java
+++ b/test-base/src/android/test/RepetitiveTest.java
@@ -26,8 +26,10 @@
  * When the annotation is present, the test method is executed the number of times specified by
  * numIterations and defaults to 1.
  *
- * {@hide} Not needed for public API.
+ * @deprecated New tests should be written using the
+ * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
  */
+@Deprecated
 @Target(ElementType.METHOD)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface RepetitiveTest {
@@ -37,4 +39,4 @@
      * @return The total number of iterations, the default is 1.
      */
     int numIterations() default 1;
-}
\ No newline at end of file
+}
diff --git a/test-legacy/Android.bp b/test-legacy/Android.bp
index 833c714..a69f422 100644
--- a/test-legacy/Android.bp
+++ b/test-legacy/Android.bp
@@ -25,7 +25,7 @@
     static_libs: [
         "android.test.base-minus-junit",
         "android.test.runner-minus-junit",
-        "android.test.mock.impl",
+        "android.test.mock_static",
     ],
 
     no_framework_libs: true,
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index e1d6e01..43b765d 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -30,3 +30,19 @@
     srcs_lib_whitelist_pkgs: ["android"],
     compile_dex: true,
 }
+
+// Build the android.test.mock_static library
+// ==========================================
+// This is only intended for inclusion in the legacy-android-test.
+// Must not be used elewhere.
+java_library_static {
+    name: "android.test.mock_static",
+
+    java_version: "1.8",
+    srcs: ["src/**/*.java"],
+
+    no_framework_libs: true,
+    libs: [
+        "framework",
+    ],
+}
diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml
index 0be1ea0..17eb029 100644
--- a/tests/ActivityViewTest/AndroidManifest.xml
+++ b/tests/ActivityViewTest/AndroidManifest.xml
@@ -57,5 +57,10 @@
                   android:exported="true"
                   android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
         </activity>
+
+        <activity android:name=".ActivityViewVisibilityActivity"
+                  android:label="AV Visibility"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+        </activity>
     </application>
 </manifest>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
index ba2e911..efcaef6 100644
--- a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
+++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
@@ -41,4 +41,10 @@
         android:text="Test Resize ActivityView"
         android:textAllCaps="false"/>
 
+    <Button
+        android:id="@+id/visibility_activity_view_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Test ActivityView Visibility"
+        android:textAllCaps="false"/>
 </LinearLayout>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
new file mode 100644
index 0000000..d29d4df
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:background="#cfd8dc">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/activity_launch_button"
+            android:layout_width="200dp"
+            android:layout_height="wrap_content"
+            android:text="Launch test activity" />
+
+        <Spinner
+            android:id="@+id/visibility_spinner"
+            android:layout_width="200dp"
+            android:layout_height="match_parent"/>
+
+    </LinearLayout>
+
+    <ActivityView
+        android:id="@+id/activity_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
index 66f0c6a..4f09c28 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
@@ -35,5 +35,8 @@
 
         findViewById(R.id.resize_activity_view_button).setOnClickListener(
                 v -> startActivity(new Intent(this, ActivityViewResizeActivity.class)));
+
+        findViewById(R.id.visibility_activity_view_button).setOnClickListener(
+                v -> startActivity(new Intent(this, ActivityViewVisibilityActivity.class)));
     }
 }
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
index ba2c764..52aba2b 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
@@ -24,12 +24,14 @@
 import android.app.Activity;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.widget.TextView;
 
 public class ActivityViewTestActivity extends Activity {
+    private static final String TAG = "ActivityViewTestActivity";
 
     private View mRoot;
     private TextView mTextView;
@@ -84,6 +86,7 @@
     }
 
     private void updateStateText(String state) {
+        Log.d(TAG, state);
         mTextView.setText(state);
     }
 
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
new file mode 100644
index 0000000..ecd2cf3
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.activityview;
+
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+
+public class ActivityViewVisibilityActivity extends Activity {
+    private static final String[] sVisibilityOptions = {"VISIBLE", "INVISIBLE", "GONE"};
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_view_visibility_activity);
+
+        final ActivityView activityView = findViewById(R.id.activity_view);
+        final Button launchButton = findViewById(R.id.activity_launch_button);
+        launchButton.setOnClickListener(v -> {
+            final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            activityView.startActivity(intent);
+        });
+
+        final Spinner visibilitySpinner = findViewById(R.id.visibility_spinner);
+        final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
+                android.R.layout.simple_spinner_item, sVisibilityOptions);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        visibilitySpinner.setAdapter(adapter);
+        visibilitySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                switch (position) {
+                    case 0:
+                        activityView.setVisibility(VISIBLE);
+                        break;
+                    case 1:
+                        activityView.setVisibility(INVISIBLE);
+                        break;
+                    case 2:
+                        activityView.setVisibility(GONE);
+                        break;
+                }
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+            }
+        });
+    }
+}
diff --git a/tests/net/java/android/net/LinkPropertiesTest.java b/tests/net/java/android/net/LinkPropertiesTest.java
index 932fee0..299fbef 100644
--- a/tests/net/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/java/android/net/LinkPropertiesTest.java
@@ -849,6 +849,18 @@
         assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
     }
 
+    private void assertParcelingIsLossless(LinkProperties source) {
+        Parcel p = Parcel.obtain();
+        source.writeToParcel(p, /* flags */ 0);
+        p.setDataPosition(0);
+        final byte[] marshalled = p.marshall();
+        p = Parcel.obtain();
+        p.unmarshall(marshalled, 0, marshalled.length);
+        p.setDataPosition(0);
+        LinkProperties dest = LinkProperties.CREATOR.createFromParcel(p);
+        assertEquals(source, dest);
+    }
+
     @Test
     public void testLinkPropertiesParcelable() throws Exception {
         LinkProperties source = new LinkProperties();
@@ -870,15 +882,12 @@
 
         source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
 
-        Parcel p = Parcel.obtain();
-        source.writeToParcel(p, /* flags */ 0);
-        p.setDataPosition(0);
-        final byte[] marshalled = p.marshall();
-        p = Parcel.obtain();
-        p.unmarshall(marshalled, 0, marshalled.length);
-        p.setDataPosition(0);
-        LinkProperties dest = LinkProperties.CREATOR.createFromParcel(p);
+        assertParcelingIsLossless(source);
+    }
 
-        assertEquals(source, dest);
+    @Test
+    public void testParcelUninitialized() throws Exception {
+        LinkProperties empty = new LinkProperties();
+        assertParcelingIsLossless(empty);
     }
 }
diff --git a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
new file mode 100644
index 0000000..4cabfc9
--- /dev/null
+++ b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.shared;
+
+import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable;
+import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable;
+
+import static org.junit.Assert.assertEquals;
+
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.ProxyInfo;
+import android.net.RouteInfo;
+import android.net.Uri;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * Tests for {@link LinkPropertiesParcelableUtil}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LinkPropertiesParcelableUtilTest {
+    private LinkProperties mLinkProperties;
+
+    private static final String TEST_LINKPROPS_IFACE = "TEST_IFACE";
+    private static final String TEST_STACKED_LINK_1_IFACE = "TEST_STACKED_IFACE_1";
+    private static final String TEST_STACKED_LINK_2_IFACE = "TEST_STACKED_IFACE_2";
+
+    @Before
+    public void setUp() {
+        mLinkProperties = makeLinkProperties(TEST_LINKPROPS_IFACE);
+        mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_1_IFACE));
+        mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_2_IFACE));
+    }
+
+    private static LinkProperties makeLinkProperties(String iface) {
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(iface);
+        lp.setLinkAddresses(Arrays.asList(
+                new LinkAddress(InetAddresses.parseNumericAddress("192.168.0.42"), 16),
+                new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::7"), 42)));
+        lp.setDnsServers(Arrays.asList(
+                InetAddresses.parseNumericAddress("2001:db8::42"),
+                InetAddresses.parseNumericAddress("192.168.1.1")
+        ));
+        lp.setValidatedPrivateDnsServers(Arrays.asList(
+                InetAddresses.parseNumericAddress("2001:db8::43"),
+                InetAddresses.parseNumericAddress("192.168.42.43")
+        ));
+        lp.setPcscfServers(Arrays.asList(
+                InetAddresses.parseNumericAddress("2001:db8::47"),
+                InetAddresses.parseNumericAddress("192.168.42.47")
+        ));
+        lp.setUsePrivateDns(true);
+        lp.setPrivateDnsServerName("test.example.com");
+        lp.setDomains("test1.example.com,test2.example.com");
+        lp.addRoute(new RouteInfo(
+                new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::44"), 45),
+                InetAddresses.parseNumericAddress("2001:db8::45"),
+                iface,
+                RouteInfo.RTN_UNICAST
+        ));
+        lp.addRoute(new RouteInfo(
+                new IpPrefix(InetAddresses.parseNumericAddress("192.168.44.45"), 16),
+                InetAddresses.parseNumericAddress("192.168.45.1"),
+                iface,
+                RouteInfo.RTN_THROW
+        ));
+        lp.setHttpProxy(new ProxyInfo("test3.example.com", 8000,
+                "excl1.example.com,excl2.example.com"));
+        lp.setMtu(5000);
+        lp.setTcpBufferSizes("1,2,3,4,5,6");
+        lp.setNat64Prefix(new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::48"), 96));
+
+        // Verify that this test does not miss any new field added later.
+        // If any added field is not included in LinkProperties#equals, assertLinkPropertiesEquals
+        // must also be updated.
+        assertEquals(14, Arrays.stream(LinkProperties.class.getDeclaredFields())
+                .filter(f -> !Modifier.isStatic(f.getModifiers())).count());
+
+        return lp;
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullInterface() {
+        mLinkProperties.setInterfaceName(null);
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullPrivateDnsServer() {
+        mLinkProperties.setPrivateDnsServerName(null);
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullDomains() {
+        mLinkProperties.setDomains(null);
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullProxy() {
+        mLinkProperties.setHttpProxy(null);
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullTcpBufferSizes() {
+        mLinkProperties.setTcpBufferSizes(null);
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_EmptyLinkAddresses() {
+        mLinkProperties.setLinkAddresses(Collections.emptyList());
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_EmptyDnses() {
+        mLinkProperties.setDnsServers(Collections.emptyList());
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_EmptyValidatedPrivateDnses() {
+        mLinkProperties.setValidatedPrivateDnsServers(Collections.emptyList());
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_EmptyRoutes() {
+        for (RouteInfo r : mLinkProperties.getAllRoutes()) {
+            mLinkProperties.removeRoute(r);
+        }
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_PacFileProxyInfo() {
+        mLinkProperties.setHttpProxy(new ProxyInfo(Uri.parse("http://pacfile.example.com")));
+        doParcelUnparcelTest();
+    }
+
+    @Test
+    public void testParcelUnparcel_NullNat64Prefix() {
+        mLinkProperties.setNat64Prefix(null);
+        doParcelUnparcelTest();
+    }
+
+    private void doParcelUnparcelTest() {
+        final LinkProperties unparceled = fromStableParcelable(toStableParcelable(mLinkProperties));
+        assertLinkPropertiesEquals(mLinkProperties, unparceled);
+    }
+
+    private static void assertLinkPropertiesEquals(LinkProperties expected, LinkProperties actual) {
+        assertEquals(expected, actual);
+
+        // LinkProperties equals() does not include stacked links
+        assertEquals(expected.getStackedLinks(), actual.getStackedLinks());
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index bf39644..2a92a7d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4683,7 +4683,7 @@
         mCellNetworkAgent.sendLinkProperties(cellLp);
         mCellNetworkAgent.connect(true);
         networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
-        verify(mNetworkManagementService, times(1)).startClatd(MOBILE_IFNAME);
+        verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME);
         Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
 
         // Clat iface up, expect stack link updated.
@@ -4710,7 +4710,7 @@
         mCellNetworkAgent.sendLinkProperties(cellLp);
         waitForIdle();
         networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
-        verify(mNetworkManagementService, times(1)).stopClatd(MOBILE_IFNAME);
+        verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
 
         // Clat iface removed, expect linkproperties revert to original one
         clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME);
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 4c52d81..9578ded 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -32,11 +32,13 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkMisc;
 import android.net.NetworkStack;
+import android.os.INetworkManagementService;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.format.DateUtils;
@@ -66,6 +68,8 @@
     LingerMonitor mMonitor;
 
     @Mock ConnectivityService mConnService;
+    @Mock INetd mNetd;
+    @Mock INetworkManagementService mNMS;
     @Mock Context mCtx;
     @Mock NetworkMisc mMisc;
     @Mock NetworkNotificationManager mNotifier;
@@ -352,7 +356,7 @@
         caps.addCapability(0);
         caps.addTransportType(transport);
         NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
-                caps, 50, mCtx, null, mMisc, mConnService);
+                caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS);
         nai.everValidated = true;
         return nai;
     }
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index bf42412..07b1d05 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -17,9 +17,7 @@
 package com.android.server.connectivity;
 
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -27,6 +25,7 @@
 import static org.mockito.Mockito.when;
 
 import android.net.ConnectivityManager;
+import android.net.INetd;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -57,6 +56,7 @@
 
     @Mock ConnectivityService mConnectivity;
     @Mock NetworkMisc mMisc;
+    @Mock INetd mNetd;
     @Mock INetworkManagementService mNms;
     @Mock InterfaceConfiguration mConfig;
     @Mock NetworkAgentInfo mNai;
@@ -65,7 +65,7 @@
     Handler mHandler;
 
     Nat464Xlat makeNat464Xlat() {
-        return new Nat464Xlat(mNms, mNai);
+        return new Nat464Xlat(mNai, mNetd, mNms);
     }
 
     @Before
@@ -129,7 +129,7 @@
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNms).startClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE));
 
         // Stacked interface up notification arrives.
         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
@@ -144,7 +144,7 @@
         // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
         nat.stop();
 
-        verify(mNms).stopClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStop(eq(BASE_IFACE));
 
         // Stacked interface removed notification arrives.
         nat.interfaceRemoved(STACKED_IFACE);
@@ -156,7 +156,7 @@
         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
         assertIdle(nat);
 
-        verifyNoMoreInteractions(mNms, mConnectivity);
+        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
     }
 
     @Test
@@ -168,7 +168,7 @@
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNms).startClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE));
 
         // Stacked interface up notification arrives.
         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
@@ -185,7 +185,7 @@
         mLooper.dispatchNext();
 
         verify(mNms).unregisterObserver(eq(nat));
-        verify(mNms).stopClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStop(eq(BASE_IFACE));
         verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
         assertTrue(c.getValue().getStackedLinks().isEmpty());
         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
@@ -194,7 +194,7 @@
         // ConnectivityService stops clat: no-op.
         nat.stop();
 
-        verifyNoMoreInteractions(mNms, mConnectivity);
+        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
     }
 
     @Test
@@ -205,13 +205,13 @@
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNms).startClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE));
 
         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
         nat.stop();
 
         verify(mNms).unregisterObserver(eq(nat));
-        verify(mNms).stopClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStop(eq(BASE_IFACE));
         assertIdle(nat);
 
         // In-flight interface up notification arrives: no-op
@@ -225,7 +225,7 @@
 
         assertIdle(nat);
 
-        verifyNoMoreInteractions(mNms, mConnectivity);
+        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
     }
 
     @Test
@@ -236,16 +236,16 @@
         nat.start();
 
         verify(mNms).registerObserver(eq(nat));
-        verify(mNms).startClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStart(eq(BASE_IFACE));
 
         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
         nat.stop();
 
         verify(mNms).unregisterObserver(eq(nat));
-        verify(mNms).stopClatd(eq(BASE_IFACE));
+        verify(mNetd).clatdStop(eq(BASE_IFACE));
         assertIdle(nat);
 
-        verifyNoMoreInteractions(mNms, mConnectivity);
+        verifyNoMoreInteractions(mNetd, mNms, mConnectivity);
     }
 
     static void assertIdle(Nat464Xlat nat) {
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
index 859a54d..e63c3b0 100644
--- a/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/tests/net/java/com/android/server/net/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.net.ipmemorystore;
 
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+
 import android.content.Context;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -26,6 +29,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.File;
+
 /** Unit tests for {@link IpMemoryStoreServiceTest}. */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -36,6 +41,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        doReturn(new File("/tmp/test.db")).when(mMockContext).getDatabasePath(anyString());
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java b/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
new file mode 100644
index 0000000..8d367e2
--- /dev/null
+++ b/tests/net/java/com/android/server/net/ipmemorystore/RelevanceUtilsTests.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.ipmemorystore;
+
+import static com.android.server.net.ipmemorystore.RelevanceUtils.CAPPED_RELEVANCE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit tests for {@link RelevanceUtils}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RelevanceUtilsTests {
+    @Test
+    public void testComputeRelevanceForTargetDate() {
+        final long dayInMillis = 24L * 60 * 60 * 1000;
+        final long base = 1_000_000L; // any given point in time
+        // Relevance when the network expires in 1000 years must be capped
+        assertEquals(CAPPED_RELEVANCE, RelevanceUtils.computeRelevanceForTargetDate(
+                base + 1000L * dayInMillis, base));
+        // Relevance when expiry is before the date must be 0
+        assertEquals(0, RelevanceUtils.computeRelevanceForTargetDate(base - 1, base));
+        // Make sure the relevance for a given target date is higher if the expiry is further
+        // in the future
+        assertTrue(RelevanceUtils.computeRelevanceForTargetDate(base + 100 * dayInMillis, base)
+                < RelevanceUtils.computeRelevanceForTargetDate(base + 150 * dayInMillis, base));
+
+        // Make sure the relevance falls slower as the expiry is closing in. This is to ensure
+        // the decay is indeed logarithmic.
+        final int relevanceAtExpiry = RelevanceUtils.computeRelevanceForTargetDate(base, base);
+        final int relevance50DaysBeforeExpiry =
+                RelevanceUtils.computeRelevanceForTargetDate(base + 50 * dayInMillis, base);
+        final int relevance100DaysBeforeExpiry =
+                RelevanceUtils.computeRelevanceForTargetDate(base + 100 * dayInMillis, base);
+        final int relevance150DaysBeforeExpiry =
+                RelevanceUtils.computeRelevanceForTargetDate(base + 150 * dayInMillis, base);
+        assertEquals(0, relevanceAtExpiry);
+        assertTrue(relevance50DaysBeforeExpiry - relevanceAtExpiry
+                < relevance100DaysBeforeExpiry - relevance50DaysBeforeExpiry);
+        assertTrue(relevance100DaysBeforeExpiry - relevance50DaysBeforeExpiry
+                < relevance150DaysBeforeExpiry - relevance100DaysBeforeExpiry);
+    }
+
+    @Test
+    public void testIncreaseRelevance() {
+        long expiry = System.currentTimeMillis();
+
+        final long firstBump = RelevanceUtils.bumpExpiryDate(expiry);
+        // Though a few milliseconds might have elapsed, the first bump should push the duration
+        // to days in the future, so unless this test takes literal days between these two lines,
+        // this should always pass.
+        assertTrue(firstBump > expiry);
+
+        expiry = 0;
+        long lastDifference = Long.MAX_VALUE;
+        // The relevance should be capped in at most this many steps. Otherwise, fail.
+        final int steps = 1000;
+        for (int i = 0; i < steps; ++i) {
+            final long newExpiry = RelevanceUtils.bumpExpiryDuration(expiry);
+            if (newExpiry == expiry) {
+                // The relevance should be capped. Make sure it is, then exit without failure.
+                assertEquals(newExpiry, RelevanceUtils.CAPPED_RELEVANCE_LIFETIME_MS);
+                return;
+            }
+            // Make sure the new expiry is further in the future than last time.
+            assertTrue(newExpiry > expiry);
+            // Also check that it was not bumped as much as the last bump, because the
+            // decay must be exponential.
+            assertTrue(newExpiry - expiry < lastDifference);
+            lastDifference = newExpiry - expiry;
+            expiry = newExpiry;
+        }
+        fail("Relevance failed to go to the maximum value after " + steps + " bumps");
+    }
+
+    @Test
+    public void testContinuity() {
+        final long expiry = System.currentTimeMillis();
+
+        // Relevance at expiry and after expiry should be the cap.
+        final int relevanceBeforeMaxLifetime = RelevanceUtils.computeRelevanceForTargetDate(expiry,
+                expiry - (RelevanceUtils.CAPPED_RELEVANCE_LIFETIME_MS + 1_000_000));
+        assertEquals(relevanceBeforeMaxLifetime, CAPPED_RELEVANCE);
+        final int relevanceForMaxLifetime = RelevanceUtils.computeRelevanceForTargetDate(expiry,
+                expiry - RelevanceUtils.CAPPED_RELEVANCE_LIFETIME_MS);
+        assertEquals(relevanceForMaxLifetime, CAPPED_RELEVANCE);
+
+        // If the max relevance is reached at the cap lifetime, one millisecond less than this
+        // should be very close. Strictly speaking this is a bit brittle, but it should be
+        // good enough for the purposes of the memory store.
+        final int relevanceForOneMillisecLessThanCap = RelevanceUtils.computeRelevanceForTargetDate(
+                expiry, expiry - RelevanceUtils.CAPPED_RELEVANCE_LIFETIME_MS + 1);
+        assertTrue(relevanceForOneMillisecLessThanCap <= CAPPED_RELEVANCE);
+        assertTrue(relevanceForOneMillisecLessThanCap >= CAPPED_RELEVANCE - 10);
+
+        // Likewise the relevance one millisecond before expiry should be very close to 0. It's
+        // fine if it rounds down to 0.
+        final int relevanceOneMillisecBeforeExpiry = RelevanceUtils.computeRelevanceForTargetDate(
+                expiry, expiry - 1);
+        assertTrue(relevanceOneMillisecBeforeExpiry <= 10);
+        assertTrue(relevanceOneMillisecBeforeExpiry >= 0);
+
+        final int relevanceAtExpiry = RelevanceUtils.computeRelevanceForTargetDate(expiry, expiry);
+        assertEquals(relevanceAtExpiry, 0);
+        final int relevanceAfterExpiry = RelevanceUtils.computeRelevanceForTargetDate(expiry,
+                expiry + 1_000_000);
+        assertEquals(relevanceAfterExpiry, 0);
+    }
+
+    // testIncreaseRelevance makes sure bumping the expiry continuously always yields a
+    // monotonically increasing date as a side effect, but this tests that the relevance (as
+    // opposed to the expiry date) increases monotonically with increasing periods.
+    @Test
+    public void testMonotonicity() {
+        // Hopefully the relevance is granular enough to give a different value for every one
+        // of this number of steps.
+        final int steps = 40;
+        final long expiry = System.currentTimeMillis();
+
+        int lastRelevance = -1;
+        for (int i = 0; i < steps; ++i) {
+            final long date = expiry - i * (RelevanceUtils.CAPPED_RELEVANCE_LIFETIME_MS / steps);
+            final int relevance = RelevanceUtils.computeRelevanceForTargetDate(expiry, date);
+            assertTrue(relevance > lastRelevance);
+            lastRelevance = relevance;
+        }
+    }
+}
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index c6f9152..ab4805f 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -16,6 +16,7 @@
 
 #include "ResourceUtils.h"
 
+#include <algorithm>
 #include <sstream>
 
 #include "android-base/stringprintf.h"
@@ -503,6 +504,14 @@
   if (entry.first == trimmed_str) {
     return entry.second;
   }
+
+  // Try parsing codename from "[codename].[preview_sdk_fingerprint]" value.
+  const StringPiece::const_iterator begin = std::begin(trimmed_str);
+  const StringPiece::const_iterator end = std::end(trimmed_str);
+  const StringPiece::const_iterator codename_end = std::find(begin, end, '.');
+  if (codename_end != end && entry.first == trimmed_str.substr(begin, codename_end)) {
+    return entry.second;
+  }
   return {};
 }
 
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 5ce4640..9018b0f 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -16,6 +16,7 @@
 
 #include "ResourceUtils.h"
 
+#include "SdkConstants.h"
 #include "Resource.h"
 #include "test/Test.h"
 
@@ -212,6 +213,17 @@
               Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened))));
 }
 
+TEST(ResourceUtilsTest, ParseSdkVersionWithCodename) {
+  const android::StringPiece codename =
+      GetDevelopmentSdkCodeNameAndVersion().first;
+  const int version = GetDevelopmentSdkCodeNameAndVersion().second;
+
+  EXPECT_THAT(ResourceUtils::ParseSdkVersion(codename), Eq(Maybe<int>(version)));
+  EXPECT_THAT(
+      ResourceUtils::ParseSdkVersion(codename.to_string() + ".fingerprint"),
+      Eq(Maybe<int>(version)));
+}
+
 TEST(ResourceUtilsTest, StringBuilderWhitespaceRemoval) {
   EXPECT_THAT(ResourceUtils::StringBuilder()
                   .AppendText("    hey guys ")
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 85bf6f2..5812ec4 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -213,6 +213,27 @@
   return true;
 }
 
+static bool AddDeprecatedUsesFeatures(xml::Element* el, SourcePathDiagnostics* diag) {
+  if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
+    if (attr->value.empty()) {
+      return true;
+    }
+
+    // Add "android.hardware.fingerprint" when "android.hardware.biometric.fingerprint" is found,
+    // since the former is deprecated in Q and the latter is not present pre-Q. (see b/115639644)
+    if (attr->value == "android.hardware.biometrics.fingerprint") {
+      auto element = el->CloneElement([&](const xml::Element& el, xml::Element* out_el) {
+        xml::Attribute* cloned_attr = out_el->FindOrCreateAttribute(xml::kSchemaAndroid, "name");
+        cloned_attr->value = "android.hardware.fingerprint";
+      });
+
+      el->parent->AppendChild(std::move(element));
+    }
+  }
+
+  return true;
+}
+
 bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
                                IDiagnostics* diag) {
   // First verify some options.
@@ -247,6 +268,7 @@
   // Common <uses-feature> actions.
   xml::XmlNodeAction uses_feature_action;
   uses_feature_action.Action(VerifyUsesFeature);
+  uses_feature_action.Action(AddDeprecatedUsesFeatures);
 
   // Common component actions.
   xml::XmlNodeAction component_action;
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index adea627..fcc9f55 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -832,4 +832,36 @@
   EXPECT_THAT(Verify(input), NotNull());
 }
 
+TEST_F(ManifestFixerTest, UsesFeatureAddDeprecated) {
+  std::string input = R"(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android">
+        <uses-feature android:name="android.hardware.biometrics.fingerprint" />
+        <feature-group>
+          <uses-feature android:name="android.hardware.biometrics.fingerprint" />
+        </feature-group>
+      </manifest>)";
+
+  std::unique_ptr<xml::XmlResource> manifest = Verify(input);
+  ASSERT_THAT(manifest, NotNull());
+  EXPECT_THAT(manifest->root->FindChildWithAttribute("", "uses-feature",
+                                                     xml::kSchemaAndroid, "name",
+                                                     "android.hardware.biometrics.fingerprint"),
+              Ne(nullptr));
+  EXPECT_THAT(manifest->root->FindChildWithAttribute("", "uses-feature",
+                                                     xml::kSchemaAndroid, "name",
+                                                     "android.hardware.fingerprint"),
+              Ne(nullptr));
+
+  xml::Element* feature_group = manifest->root->FindChild("", "feature-group");
+  ASSERT_THAT(feature_group, Ne(nullptr));
+
+  EXPECT_THAT(feature_group->FindChildWithAttribute("", "uses-feature", xml::kSchemaAndroid, "name",
+                                                    "android.hardware.biometrics.fingerprint"),
+              Ne(nullptr));
+  EXPECT_THAT(feature_group->FindChildWithAttribute("", "uses-feature", xml::kSchemaAndroid, "name",
+                                                    "android.hardware.fingerprint"),
+              Ne(nullptr));
+}
+
 }  // namespace aapt
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 85871fe..e019f28 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -145,11 +145,23 @@
          */
         public static final int SUITE_B_192 = 10;
 
+        /**
+         * WPA pre-shared key with stronger SHA256-based algorithms.
+         * @hide
+         */
+        public static final int WPA_PSK_SHA256 = 11;
+
+        /**
+         * WPA using EAP authentication with stronger SHA256-based algorithms.
+         * @hide
+         */
+        public static final int WPA_EAP_SHA256 = 12;
+
         public static final String varName = "key_mgmt";
 
         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
                 "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
-                "SAE", "OWE", "SUITE_B_192"};
+                "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" };
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 840af5d..35fba3d 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkUtils;
@@ -470,6 +471,7 @@
     }
 
     /** {@hide} */
+    @SystemApi
     public boolean isOsuAp() {
         return mOsuAp;
     }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 559f4ad..801342d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -236,9 +236,11 @@
     public static final int WIFI_CREDENTIAL_FORGOT = 1;
 
     /** @hide */
+    @SystemApi
     public static final int PASSPOINT_HOME_NETWORK = 0;
 
     /** @hide */
+    @SystemApi
     public static final int PASSPOINT_ROAMING_NETWORK = 1;
 
     /**
@@ -1219,7 +1221,11 @@
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs(
             @NonNull List<ScanResult> scanResults) {
         List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>();
@@ -1258,7 +1264,11 @@
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders(
             List<ScanResult> scanResults) {
         try {
@@ -1281,7 +1291,11 @@
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(
             @NonNull Set<OsuProvider> osuProviders) {
         try {
@@ -1727,7 +1741,13 @@
      * @param fqdn The FQDN of the Passpoint configuration to be removed
      * @throws IllegalArgumentException if no configuration is associated with the given FQDN.
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public void removePasspointConfiguration(String fqdn) {
         try {
             if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
@@ -1745,7 +1765,13 @@
      *
      * @return A list of {@link PasspointConfiguration}
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+     * @deprecated This is no longer supported.
      */
+    @Deprecated
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public List<PasspointConfiguration> getPasspointConfigurations() {
         try {
             return mService.getPasspointConfigurations();
@@ -4323,6 +4349,11 @@
      * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD
+    })
     public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback,
             @Nullable Handler handler) {
         Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
index 6d82ca1..f91790f 100644
--- a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
+++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.hotspot2;
 
+import android.annotation.SystemApi;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.wifi.WifiSsid;
@@ -36,16 +37,19 @@
  *
  * @hide
  */
+@SystemApi
 public final class OsuProvider implements Parcelable {
     /**
      * OSU (Online Sign-Up) method: OMA DM (Open Mobile Alliance Device Management).
      * For more info, refer to Section 8.3 of the Hotspot 2.0 Release 2 Technical Specification.
+     * @hide
      */
     public static final int METHOD_OMA_DM = 0;
 
     /**
      * OSU (Online Sign-Up) method: SOAP XML SPP (Subscription Provisioning Protocol).
      * For more info, refer to Section 8.4 of the Hotspot 2.0 Release 2 Technical Specification.
+     * @hide
      */
     public static final int METHOD_SOAP_XML_SPP = 1;
 
@@ -84,6 +88,7 @@
      */
     private final Icon mIcon;
 
+    /** @hide */
     public OsuProvider(WifiSsid osuSsid, Map<String, String> friendlyNames,
             String serviceDescription, Uri serverUri, String nai, List<Integer> methodList,
             Icon icon) {
@@ -104,6 +109,7 @@
      * Copy constructor.
      *
      * @param source The source to copy from
+     * @hide
      */
     public OsuProvider(OsuProvider source) {
         if (source == null) {
@@ -130,10 +136,12 @@
         mIcon = source.mIcon;
     }
 
+    /** @hide */
     public WifiSsid getOsuSsid() {
         return mOsuSsid;
     }
 
+    /** @hide */
     public void setOsuSsid(WifiSsid osuSsid) {
         mOsuSsid = osuSsid;
     }
@@ -162,10 +170,12 @@
         return mFriendlyNames.get(mFriendlyNames.keySet().stream().findFirst().get());
     }
 
+    /** @hide */
     public Map<String, String> getFriendlyNameList() {
         return mFriendlyNames;
     }
 
+    /** @hide */
     public String getServiceDescription() {
         return mServiceDescription;
     }
@@ -174,14 +184,17 @@
         return mServerUri;
     }
 
+    /** @hide */
     public String getNetworkAccessIdentifier() {
         return mNetworkAccessIdentifier;
     }
 
+    /** @hide */
     public List<Integer> getMethodList() {
         return mMethodList;
     }
 
+    /** @hide */
     public Icon getIcon() {
         return mIcon;
     }
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index a62d63c..1ee874a 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi.hotspot2;
 
+import android.annotation.SystemApi;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 
@@ -25,6 +26,7 @@
  *
  * @hide
  */
+@SystemApi
 public abstract class ProvisioningCallback {
 
     /**