Merge changes I4054d6f4,Ib14e9a93,Iafbe6d51

* changes:
  CpuStats - Do not write debug entries to dump output
  Set ThreadLocalWorkSource when delivering Alarms
  Add WorkSource.getAttributionUid()
diff --git a/Android.bp b/Android.bp
index 8e53738..e63463c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -191,6 +191,10 @@
         "core/java/android/hardware/input/IInputDevicesChangedListener.aidl",
         "core/java/android/hardware/input/ITabletModeChangedListener.aidl",
         "core/java/android/hardware/iris/IIrisService.aidl",
+        "core/java/android/hardware/location/IActivityRecognitionHardware.aidl",
+        "core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl",
+        "core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl",
+        "core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl",
         "core/java/android/hardware/location/IGeofenceHardware.aidl",
         "core/java/android/hardware/location/IGeofenceHardwareCallback.aidl",
         "core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl",
@@ -761,8 +765,6 @@
     required: [
         // TODO: remove gps_debug when the build system propagates "required" properly.
         "gps_debug.conf",
-        // Loaded with System.loadLibrary by android.view.textclassifier
-        "libmedia2_jni",
     ],
 
     dxflags: [
diff --git a/api/current.txt b/api/current.txt
index 482d498..3bb6957 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9625,7 +9625,7 @@
 
   public abstract class Context {
     ctor public Context();
-    method public abstract boolean bindIsolatedService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String);
+    method public boolean bindIsolatedService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String);
     method public abstract boolean bindService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int);
     method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String);
     method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9678,7 +9678,7 @@
     method public abstract java.io.File getNoBackupFilesDir();
     method public abstract java.io.File getObbDir();
     method public abstract java.io.File[] getObbDirs();
-    method public abstract String getOpPackageName();
+    method public String getOpPackageName();
     method public abstract String getPackageCodePath();
     method public abstract android.content.pm.PackageManager getPackageManager();
     method public abstract String getPackageName();
@@ -9745,7 +9745,7 @@
     method public abstract void unbindService(@NonNull android.content.ServiceConnection);
     method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
     method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
-    method public abstract void updateServiceGroup(@NonNull android.content.ServiceConnection, int, int);
+    method public void updateServiceGroup(@NonNull android.content.ServiceConnection, int, int);
     field public static final String ACCESSIBILITY_SERVICE = "accessibility";
     field public static final String ACCOUNT_SERVICE = "account";
     field public static final String ACTIVITY_SERVICE = "activity";
@@ -9839,7 +9839,6 @@
   public class ContextWrapper extends android.content.Context {
     ctor public ContextWrapper(android.content.Context);
     method protected void attachBaseContext(android.content.Context);
-    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9889,7 +9888,6 @@
     method public java.io.File getNoBackupFilesDir();
     method public java.io.File getObbDir();
     method public java.io.File[] getObbDirs();
-    method public String getOpPackageName();
     method public String getPackageCodePath();
     method public android.content.pm.PackageManager getPackageManager();
     method public String getPackageName();
@@ -9945,7 +9943,6 @@
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
-    method public void updateServiceGroup(android.content.ServiceConnection, int, int);
   }
 
   @Deprecated public class CursorLoader extends android.content.AsyncTaskLoader<android.database.Cursor> {
@@ -10221,7 +10218,7 @@
     field public static final String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
     field public static final String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
     field public static final String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
-    field public static final String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
+    field @Deprecated public static final String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
     field public static final String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
     field public static final String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
     field public static final String ACTION_PACKAGES_SUSPENDED = "android.intent.action.PACKAGES_SUSPENDED";
@@ -28912,24 +28909,24 @@
     field public static final android.os.Parcelable.Creator<android.net.RouteInfo> CREATOR;
   }
 
-  public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
+  @Deprecated public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     ctor @Deprecated public SSLCertificateSocketFactory(int);
-    method public java.net.Socket createSocket(java.net.Socket, String, int, boolean) throws java.io.IOException;
-    method public java.net.Socket createSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
-    method public java.net.Socket createSocket(java.net.InetAddress, int) throws java.io.IOException;
-    method public java.net.Socket createSocket(String, int, java.net.InetAddress, int) throws java.io.IOException;
-    method public java.net.Socket createSocket(String, int) throws java.io.IOException;
-    method public static javax.net.SocketFactory getDefault(int);
-    method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
-    method public String[] getDefaultCipherSuites();
-    method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
-    method public byte[] getNpnSelectedProtocol(java.net.Socket);
-    method public String[] getSupportedCipherSuites();
-    method public void setHostname(java.net.Socket, String);
-    method public void setKeyManagers(javax.net.ssl.KeyManager[]);
-    method public void setNpnProtocols(byte[][]);
-    method public void setTrustManagers(javax.net.ssl.TrustManager[]);
-    method public void setUseSessionTickets(java.net.Socket, boolean);
+    method @Deprecated public java.net.Socket createSocket(java.net.Socket, String, int, boolean) throws java.io.IOException;
+    method @Deprecated public java.net.Socket createSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
+    method @Deprecated public java.net.Socket createSocket(java.net.InetAddress, int) throws java.io.IOException;
+    method @Deprecated public java.net.Socket createSocket(String, int, java.net.InetAddress, int) throws java.io.IOException;
+    method @Deprecated public java.net.Socket createSocket(String, int) throws java.io.IOException;
+    method @Deprecated public static javax.net.SocketFactory getDefault(int);
+    method @Deprecated public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
+    method @Deprecated public String[] getDefaultCipherSuites();
+    method @Deprecated public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
+    method @Deprecated public byte[] getNpnSelectedProtocol(java.net.Socket);
+    method @Deprecated public String[] getSupportedCipherSuites();
+    method @Deprecated public void setHostname(java.net.Socket, String);
+    method @Deprecated public void setKeyManagers(javax.net.ssl.KeyManager[]);
+    method @Deprecated public void setNpnProtocols(byte[][]);
+    method @Deprecated public void setTrustManagers(javax.net.ssl.TrustManager[]);
+    method @Deprecated public void setUseSessionTickets(java.net.Socket, boolean);
   }
 
   public final class SSLSessionCache {
@@ -37896,18 +37893,18 @@
     method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
     method @Deprecated public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
     method public static String getDocumentId(android.net.Uri);
-    method public static android.os.Bundle getDocumentMetadata(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
+    method @Nullable public static android.os.Bundle getDocumentMetadata(@NonNull android.content.ContentInterface, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
     method @Deprecated public static android.os.Bundle getDocumentMetadata(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentInterface, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method @Deprecated public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public static String getRootId(android.net.Uri);
     method public static String getSearchDocumentsQuery(android.net.Uri);
     method public static String getTreeDocumentId(android.net.Uri);
-    method public static boolean isChildDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+    method public static boolean isChildDocument(@NonNull android.content.ContentInterface, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
     method @Deprecated public static boolean isChildDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
     method public static boolean isDocumentUri(android.content.Context, @Nullable android.net.Uri);
-    method public static boolean isRootUri(android.content.Context, @Nullable android.net.Uri);
-    method public static boolean isRootsUri(android.content.Context, @Nullable android.net.Uri);
+    method public static boolean isRootUri(@NonNull android.content.Context, @Nullable android.net.Uri);
+    method public static boolean isRootsUri(@NonNull android.content.Context, @Nullable android.net.Uri);
     method public static boolean isTreeUri(android.net.Uri);
     method public static android.net.Uri moveDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
     method @Deprecated public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
@@ -38000,7 +37997,7 @@
     method public void deleteDocument(String) throws java.io.FileNotFoundException;
     method public void ejectRoot(String);
     method public android.provider.DocumentsContract.Path findDocumentPath(@Nullable String, String) throws java.io.FileNotFoundException;
-    method @Nullable public android.os.Bundle getDocumentMetadata(String) throws java.io.FileNotFoundException;
+    method @Nullable public android.os.Bundle getDocumentMetadata(@NonNull String) throws java.io.FileNotFoundException;
     method public String[] getDocumentStreamTypes(String, String);
     method public String getDocumentType(String) throws java.io.FileNotFoundException;
     method public final String getType(android.net.Uri);
@@ -38025,7 +38022,7 @@
     method public android.database.Cursor queryRecentDocuments(String, String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(String, String, String[]) throws java.io.FileNotFoundException;
-    method public android.database.Cursor querySearchDocuments(String, String[], android.os.Bundle) throws java.io.FileNotFoundException;
+    method public android.database.Cursor querySearchDocuments(@NonNull String, @Nullable String[], @NonNull android.os.Bundle) throws java.io.FileNotFoundException;
     method public void removeDocument(String, String) throws java.io.FileNotFoundException;
     method public String renameDocument(String, String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(String);
@@ -45025,7 +45022,9 @@
     field public static final int PROTOCOL_IP = 0; // 0x0
     field public static final int PROTOCOL_IPV4V6 = 2; // 0x2
     field public static final int PROTOCOL_IPV6 = 1; // 0x1
+    field public static final int PROTOCOL_NON_IP = 4; // 0x4
     field public static final int PROTOCOL_PPP = 3; // 0x3
+    field public static final int PROTOCOL_UNSTRUCTURED = 5; // 0x5
     field public static final int TYPE_CBS = 128; // 0x80
     field public static final int TYPE_DEFAULT = 17; // 0x11
     field public static final int TYPE_DUN = 8; // 0x8
diff --git a/api/removed.txt b/api/removed.txt
index 2c567e0..e232227 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -325,7 +325,7 @@
   @IntDef({0x0, 0xa, 0x14, 0x1e}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface NetworkBadging.Badging {
   }
 
-  public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
+  @Deprecated public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
     method @Deprecated public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index ae5e288..aac7a98 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1776,8 +1776,13 @@
   }
 
   public final class ColorDisplayManager {
+    method @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) public int getTransformCapabilities();
     method @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) public boolean setAppSaturationLevel(@NonNull String, @IntRange(from=0, to=100) int);
     method @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) public boolean setSaturationLevel(@IntRange(from=0, to=100) int);
+    field public static final int CAPABILITY_HARDWARE_ACCELERATION_GLOBAL = 2; // 0x2
+    field public static final int CAPABILITY_HARDWARE_ACCELERATION_PER_APP = 4; // 0x4
+    field public static final int CAPABILITY_NONE = 0; // 0x0
+    field public static final int CAPABILITY_PROTECTED_CONTENT = 1; // 0x1
   }
 
   public final class DisplayManager {
@@ -4493,7 +4498,6 @@
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void connect(int, android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disable(int, android.net.wifi.WifiManager.ActionListener);
-    method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void disableEphemeralNetwork(String);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void forget(int, android.net.wifi.WifiManager.ActionListener);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) 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(@NonNull java.util.List<android.net.wifi.ScanResult>);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
@@ -4727,7 +4731,7 @@
     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_INVALID_URL_FORMAT_FOR_OSU = 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
@@ -5444,6 +5448,7 @@
     field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
     field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+    field public static final String NAMESPACE_NOTIFICATION_ASSISTANT = "notification_assistant";
   }
 
   public static interface DeviceConfig.OnPropertyChangedListener {
@@ -6752,42 +6757,211 @@
   }
 
   public final class DataFailCause {
+    field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
+    field public static final int ACCESS_BLOCK = 2087; // 0x827
+    field public static final int ACCESS_BLOCK_ALL = 2088; // 0x828
+    field public static final int ACCESS_CLASS_DSAC_REJECTION = 2108; // 0x83c
+    field public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128; // 0x850
+    field public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 48; // 0x30
     field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
     field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
     field public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 65; // 0x41
+    field public static final int APN_DISABLED = 2045; // 0x7fd
+    field public static final int APN_DISALLOWED_ON_ROAMING = 2059; // 0x80b
+    field public static final int APN_MISMATCH = 2054; // 0x806
+    field public static final int APN_PARAMETERS_CHANGED = 2060; // 0x80c
+    field public static final int APN_PENDING_HANDOVER = 2041; // 0x7f9
     field public static final int APN_TYPE_CONFLICT = 112; // 0x70
     field public static final int AUTH_FAILURE_ON_EMERGENCY_CALL = 122; // 0x7a
+    field public static final int BEARER_HANDLING_NOT_SUPPORTED = 60; // 0x3c
+    field public static final int CALL_DISALLOWED_IN_ROAMING = 2068; // 0x814
+    field public static final int CALL_PREEMPT_BY_EMERGENCY_APN = 127; // 0x7f
+    field public static final int CANNOT_ENCODE_OTA_MESSAGE = 2159; // 0x86f
+    field public static final int CDMA_ALERT_STOP = 2077; // 0x81d
+    field public static final int CDMA_INCOMING_CALL = 2076; // 0x81c
+    field public static final int CDMA_INTERCEPT = 2073; // 0x819
+    field public static final int CDMA_LOCK = 2072; // 0x818
+    field public static final int CDMA_RELEASE_DUE_TO_SO_REJECTION = 2075; // 0x81b
+    field public static final int CDMA_REORDER = 2074; // 0x81a
+    field public static final int CDMA_RETRY_ORDER = 2086; // 0x826
+    field public static final int CHANNEL_ACQUISITION_FAILURE = 2078; // 0x81e
+    field public static final int CLOSE_IN_PROGRESS = 2030; // 0x7ee
+    field public static final int COLLISION_WITH_NETWORK_INITIATED_REQUEST = 56; // 0x38
     field public static final int COMPANION_IFACE_IN_USE = 118; // 0x76
+    field public static final int CONCURRENT_SERVICES_INCOMPATIBLE = 2083; // 0x823
+    field public static final int CONCURRENT_SERVICES_NOT_ALLOWED = 2091; // 0x82b
+    field public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 2080; // 0x820
     field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
+    field public static final int CONGESTION = 2106; // 0x83a
+    field public static final int CONNECTION_RELEASED = 2113; // 0x841
+    field public static final int CS_DOMAIN_NOT_AVAILABLE = 2181; // 0x885
+    field public static final int CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 2188; // 0x88c
+    field public static final int DATA_PLAN_EXPIRED = 2198; // 0x896
+    field public static final int DATA_ROAMING_SETTINGS_DISABLED = 2064; // 0x810
+    field public static final int DATA_SETTINGS_DISABLED = 2063; // 0x80f
+    field public static final int DBM_OR_SMS_IN_PROGRESS = 2211; // 0x8a3
+    field public static final int DDS_SWITCHED = 2065; // 0x811
+    field public static final int DDS_SWITCH_IN_PROGRESS = 2067; // 0x813
+    field public static final int DRB_RELEASED_BY_RRC = 2112; // 0x840
+    field public static final int DS_EXPLICIT_DEACTIVATION = 2125; // 0x84d
+    field public static final int DUAL_SWITCH = 2227; // 0x8b3
+    field public static final int DUN_CALL_DISALLOWED = 2056; // 0x808
+    field public static final int DUPLICATE_BEARER_ID = 2118; // 0x846
+    field public static final int EHRPD_TO_HRPD_FALLBACK = 2049; // 0x801
+    field public static final int EMBMS_NOT_ENABLED = 2193; // 0x891
+    field public static final int EMBMS_REGULAR_DEACTIVATION = 2195; // 0x893
     field public static final int EMERGENCY_IFACE_ONLY = 116; // 0x74
+    field public static final int EMERGENCY_MODE = 2221; // 0x8ad
     field public static final int EMM_ACCESS_BARRED = 115; // 0x73
     field public static final int EMM_ACCESS_BARRED_INFINITE_RETRY = 121; // 0x79
+    field public static final int EMM_ATTACH_FAILED = 2115; // 0x843
+    field public static final int EMM_ATTACH_STARTED = 2116; // 0x844
+    field public static final int EMM_DETACHED = 2114; // 0x842
+    field public static final int EMM_T3417_EXPIRED = 2130; // 0x852
+    field public static final int EMM_T3417_EXT_EXPIRED = 2131; // 0x853
+    field public static final int EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 2178; // 0x882
+    field public static final int EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 2179; // 0x883
     field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
+    field public static final int ESM_BAD_OTA_MESSAGE = 2122; // 0x84a
+    field public static final int ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 2120; // 0x848
+    field public static final int ESM_COLLISION_SCENARIOS = 2119; // 0x847
+    field public static final int ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 2124; // 0x84c
+    field public static final int ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 2123; // 0x84b
+    field public static final int ESM_FAILURE = 2182; // 0x886
     field public static final int ESM_INFO_NOT_RECEIVED = 53; // 0x35
+    field public static final int ESM_LOCAL_CAUSE_NONE = 2126; // 0x84e
+    field public static final int ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 2121; // 0x849
+    field public static final int ESM_PROCEDURE_TIME_OUT = 2155; // 0x86b
+    field public static final int ESM_UNKNOWN_EPS_BEARER_CONTEXT = 2111; // 0x83f
+    field public static final int EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 2201; // 0x899
+    field public static final int EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 2200; // 0x898
+    field public static final int EVDO_HDR_CHANGED = 2202; // 0x89a
+    field public static final int EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 2206; // 0x89e
+    field public static final int EVDO_HDR_EXITED = 2203; // 0x89b
+    field public static final int EVDO_HDR_NO_SESSION = 2204; // 0x89c
+    field public static final int EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 2205; // 0x89d
+    field public static final int FADE = 2217; // 0x8a9
+    field public static final int FAILED_TO_ACQUIRE_COLOCATED_HDR = 2207; // 0x89f
     field public static final int FEATURE_NOT_SUPP = 40; // 0x28
     field public static final int FILTER_SEMANTIC_ERROR = 44; // 0x2c
     field public static final int FILTER_SYTAX_ERROR = 45; // 0x2d
+    field public static final int FORBIDDEN_APN_NAME = 2066; // 0x812
     field public static final int GPRS_REGISTRATION_FAIL = -2; // 0xfffffffe
+    field public static final int GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 2097; // 0x831
+    field public static final int GPRS_SERVICES_NOT_ALLOWED = 2098; // 0x832
+    field public static final int GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 2103; // 0x837
+    field public static final int HANDOFF_PREFERENCE_CHANGED = 2251; // 0x8cb
+    field public static final int HDR_ACCESS_FAILURE = 2213; // 0x8a5
+    field public static final int HDR_FADE = 2212; // 0x8a4
+    field public static final int HDR_NO_LOCK_GRANTED = 2210; // 0x8a2
     field public static final int IFACE_AND_POL_FAMILY_MISMATCH = 120; // 0x78
     field public static final int IFACE_MISMATCH = 117; // 0x75
+    field public static final int ILLEGAL_ME = 2096; // 0x830
+    field public static final int ILLEGAL_MS = 2095; // 0x82f
+    field public static final int IMEI_NOT_ACCEPTED = 2177; // 0x881
+    field public static final int IMPLICITLY_DETACHED = 2100; // 0x834
+    field public static final int IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 2176; // 0x880
+    field public static final int INCOMING_CALL_REJECTED = 2092; // 0x82c
     field public static final int INSUFFICIENT_RESOURCES = 26; // 0x1a
+    field public static final int INTERFACE_IN_USE = 2058; // 0x80a
     field public static final int INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 114; // 0x72
+    field public static final int INTERNAL_EPC_NONEPC_TRANSITION = 2057; // 0x809
+    field public static final int INVALID_CONNECTION_ID = 2156; // 0x86c
+    field public static final int INVALID_DNS_ADDR = 123; // 0x7b
+    field public static final int INVALID_EMM_STATE = 2190; // 0x88e
     field public static final int INVALID_MANDATORY_INFO = 96; // 0x60
+    field public static final int INVALID_MODE = 2223; // 0x8af
     field public static final int INVALID_PCSCF_ADDR = 113; // 0x71
+    field public static final int INVALID_PCSCF_OR_DNS_ADDRESS = 124; // 0x7c
+    field public static final int INVALID_PRIMARY_NSAPI = 2158; // 0x86e
+    field public static final int INVALID_SIM_STATE = 2224; // 0x8b0
     field public static final int INVALID_TRANSACTION_ID = 81; // 0x51
+    field public static final int IPV6_ADDRESS_TRANSFER_FAILED = 2047; // 0x7ff
+    field public static final int IPV6_PREFIX_UNAVAILABLE = 2250; // 0x8ca
     field public static final int IP_ADDRESS_MISMATCH = 119; // 0x77
+    field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
+    field public static final int IRAT_HANDOVER_FAILED = 2194; // 0x892
+    field public static final int IS707B_MAX_ACCESS_PROBES = 2089; // 0x829
+    field public static final int LIMITED_TO_IPV4 = 2234; // 0x8ba
+    field public static final int LIMITED_TO_IPV6 = 2235; // 0x8bb
     field public static final int LLC_SNDCP = 25; // 0x19
+    field public static final int LOCAL_END = 2215; // 0x8a7
+    field public static final int LOCATION_AREA_NOT_ALLOWED = 2102; // 0x836
     field public static final int LOST_CONNECTION = 65540; // 0x10004
+    field public static final int LOWER_LAYER_REGISTRATION_FAILURE = 2197; // 0x895
+    field public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 2044; // 0x7fc
+    field public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 2117; // 0x845
+    field public static final int LTE_THROTTLING_NOT_REQUIRED = 2127; // 0x84f
+    field public static final int MAC_FAILURE = 2183; // 0x887
+    field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
+    field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
+    field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
+    field public static final int MAX_IPV4_CONNECTIONS = 2052; // 0x804
+    field public static final int MAX_IPV6_CONNECTIONS = 2053; // 0x805
+    field public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
     field public static final int MESSAGE_INCORRECT_SEMANTIC = 95; // 0x5f
     field public static final int MESSAGE_TYPE_UNSUPPORTED = 97; // 0x61
+    field public static final int MIP_CONFIG_FAILURE = 2050; // 0x802
+    field public static final int MIP_FA_ADMIN_PROHIBITED = 2001; // 0x7d1
+    field public static final int MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 2012; // 0x7dc
+    field public static final int MIP_FA_ENCAPSULATION_UNAVAILABLE = 2008; // 0x7d8
+    field public static final int MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 2004; // 0x7d4
+    field public static final int MIP_FA_INSUFFICIENT_RESOURCES = 2002; // 0x7d2
+    field public static final int MIP_FA_MALFORMED_REPLY = 2007; // 0x7d7
+    field public static final int MIP_FA_MALFORMED_REQUEST = 2006; // 0x7d6
+    field public static final int MIP_FA_MISSING_CHALLENGE = 2017; // 0x7e1
+    field public static final int MIP_FA_MISSING_HOME_ADDRESS = 2015; // 0x7df
+    field public static final int MIP_FA_MISSING_HOME_AGENT = 2014; // 0x7de
+    field public static final int MIP_FA_MISSING_NAI = 2013; // 0x7dd
+    field public static final int MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2003; // 0x7d3
+    field public static final int MIP_FA_REASON_UNSPECIFIED = 2000; // 0x7d0
+    field public static final int MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 2005; // 0x7d5
+    field public static final int MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 2011; // 0x7db
+    field public static final int MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 2010; // 0x7da
+    field public static final int MIP_FA_STALE_CHALLENGE = 2018; // 0x7e2
+    field public static final int MIP_FA_UNKNOWN_CHALLENGE = 2016; // 0x7e0
+    field public static final int MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 2009; // 0x7d9
+    field public static final int MIP_HA_ADMIN_PROHIBITED = 2020; // 0x7e4
+    field public static final int MIP_HA_ENCAPSULATION_UNAVAILABLE = 2029; // 0x7ed
+    field public static final int MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 2023; // 0x7e7
+    field public static final int MIP_HA_INSUFFICIENT_RESOURCES = 2021; // 0x7e5
+    field public static final int MIP_HA_MALFORMED_REQUEST = 2025; // 0x7e9
+    field public static final int MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2022; // 0x7e6
+    field public static final int MIP_HA_REASON_UNSPECIFIED = 2019; // 0x7e3
+    field public static final int MIP_HA_REGISTRATION_ID_MISMATCH = 2024; // 0x7e8
+    field public static final int MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 2028; // 0x7ec
+    field public static final int MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 2027; // 0x7eb
+    field public static final int MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 2026; // 0x7ea
     field public static final int MISSING_UNKNOWN_APN = 27; // 0x1b
+    field public static final int MODEM_APP_PREEMPTED = 2032; // 0x7f0
+    field public static final int MODEM_RESTART = 2037; // 0x7f5
+    field public static final int MSC_TEMPORARILY_NOT_REACHABLE = 2180; // 0x884
     field public static final int MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101; // 0x65
     field public static final int MSG_TYPE_NONCOMPATIBLE_STATE = 98; // 0x62
+    field public static final int MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 2099; // 0x833
+    field public static final int MULTIPLE_PDP_CALL_NOT_ALLOWED = 2192; // 0x890
     field public static final int MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 55; // 0x37
+    field public static final int NAS_LAYER_FAILURE = 2191; // 0x88f
+    field public static final int NAS_REQUEST_REJECTED_BY_NETWORK = 2167; // 0x877
     field public static final int NAS_SIGNALLING = 14; // 0xe
     field public static final int NETWORK_FAILURE = 38; // 0x26
+    field public static final int NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 2154; // 0x86a
+    field public static final int NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 2153; // 0x869
+    field public static final int NETWORK_INITIATED_TERMINATION = 2031; // 0x7ef
     field public static final int NONE = 0; // 0x0
+    field public static final int NON_IP_NOT_SUPPORTED = 2069; // 0x815
+    field public static final int NORMAL_RELEASE = 2218; // 0x8aa
+    field public static final int NO_CDMA_SERVICE = 2084; // 0x824
+    field public static final int NO_COLLOCATED_HDR = 2225; // 0x8b1
+    field public static final int NO_EPS_BEARER_CONTEXT_ACTIVATED = 2189; // 0x88d
+    field public static final int NO_GPRS_CONTEXT = 2094; // 0x82e
+    field public static final int NO_HYBRID_HDR_SERVICE = 2209; // 0x8a1
+    field public static final int NO_PDP_CONTEXT_ACTIVATED = 2107; // 0x83b
+    field public static final int NO_RESPONSE_FROM_BASE_STATION = 2081; // 0x821
+    field public static final int NO_SERVICE = 2216; // 0x8a8
+    field public static final int NO_SERVICE_ON_GATEWAY = 2093; // 0x82d
     field public static final int NSAPI_IN_USE = 35; // 0x23
+    field public static final int NULL_APN_DISALLOWED = 2061; // 0x80d
     field public static final int OEM_DCFAILCAUSE_1 = 4097; // 0x1001
     field public static final int OEM_DCFAILCAUSE_10 = 4106; // 0x100a
     field public static final int OEM_DCFAILCAUSE_11 = 4107; // 0x100b
@@ -6803,33 +6977,126 @@
     field public static final int OEM_DCFAILCAUSE_7 = 4103; // 0x1007
     field public static final int OEM_DCFAILCAUSE_8 = 4104; // 0x1008
     field public static final int OEM_DCFAILCAUSE_9 = 4105; // 0x1009
+    field public static final int ONLY_IPV4V6_ALLOWED = 57; // 0x39
     field public static final int ONLY_IPV4_ALLOWED = 50; // 0x32
     field public static final int ONLY_IPV6_ALLOWED = 51; // 0x33
+    field public static final int ONLY_NON_IP_ALLOWED = 58; // 0x3a
     field public static final int ONLY_SINGLE_BEARER_ALLOWED = 52; // 0x34
     field public static final int OPERATOR_BARRED = 8; // 0x8
+    field public static final int OTASP_COMMIT_IN_PROGRESS = 2208; // 0x8a0
     field public static final int PDN_CONN_DOES_NOT_EXIST = 54; // 0x36
+    field public static final int PDN_INACTIVITY_TIMER_EXPIRED = 2051; // 0x803
+    field public static final int PDN_IPV4_CALL_DISALLOWED = 2033; // 0x7f1
+    field public static final int PDN_IPV4_CALL_THROTTLED = 2034; // 0x7f2
+    field public static final int PDN_IPV6_CALL_DISALLOWED = 2035; // 0x7f3
+    field public static final int PDN_IPV6_CALL_THROTTLED = 2036; // 0x7f4
+    field public static final int PDN_NON_IP_CALL_DISALLOWED = 2071; // 0x817
+    field public static final int PDN_NON_IP_CALL_THROTTLED = 2070; // 0x816
+    field public static final int PDP_ACTIVATE_MAX_RETRY_FAILED = 2109; // 0x83d
+    field public static final int PDP_DUPLICATE = 2104; // 0x838
+    field public static final int PDP_ESTABLISH_TIMEOUT_EXPIRED = 2161; // 0x871
+    field public static final int PDP_INACTIVE_TIMEOUT_EXPIRED = 2163; // 0x873
+    field public static final int PDP_LOWERLAYER_ERROR = 2164; // 0x874
+    field public static final int PDP_MODIFY_COLLISION = 2165; // 0x875
+    field public static final int PDP_MODIFY_TIMEOUT_EXPIRED = 2162; // 0x872
+    field public static final int PDP_PPP_NOT_SUPPORTED = 2038; // 0x7f6
     field public static final int PDP_WITHOUT_ACTIVE_TFT = 46; // 0x2e
+    field public static final int PHONE_IN_USE = 2222; // 0x8ae
+    field public static final int PHYSICAL_LINK_CLOSE_IN_PROGRESS = 2040; // 0x7f8
+    field public static final int PLMN_NOT_ALLOWED = 2101; // 0x835
+    field public static final int PPP_AUTH_FAILURE = 2229; // 0x8b5
+    field public static final int PPP_CHAP_FAILURE = 2232; // 0x8b8
+    field public static final int PPP_CLOSE_IN_PROGRESS = 2233; // 0x8b9
+    field public static final int PPP_OPTION_MISMATCH = 2230; // 0x8b6
+    field public static final int PPP_PAP_FAILURE = 2231; // 0x8b7
+    field public static final int PPP_TIMEOUT = 2228; // 0x8b4
     field public static final int PREF_RADIO_TECH_CHANGED = -4; // 0xfffffffc
+    field public static final int PROFILE_BEARER_INCOMPATIBLE = 2042; // 0x7fa
     field public static final int PROTOCOL_ERRORS = 111; // 0x6f
     field public static final int QOS_NOT_ACCEPTED = 37; // 0x25
+    field public static final int RADIO_ACCESS_BEARER_FAILURE = 2110; // 0x83e
+    field public static final int RADIO_ACCESS_BEARER_SETUP_FAILURE = 2160; // 0x870
     field public static final int RADIO_NOT_AVAILABLE = 65537; // 0x10001
     field public static final int RADIO_POWER_OFF = -5; // 0xfffffffb
+    field public static final int REDIRECTION_OR_HANDOFF_IN_PROGRESS = 2220; // 0x8ac
     field public static final int REGISTRATION_FAIL = -1; // 0xffffffff
     field public static final int REGULAR_DEACTIVATION = 36; // 0x24
+    field public static final int REJECTED_BY_BASE_STATION = 2082; // 0x822
+    field public static final int RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 2173; // 0x87d
+    field public static final int RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 2174; // 0x87e
+    field public static final int RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 2171; // 0x87b
+    field public static final int RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 2175; // 0x87f
+    field public static final int RRC_CONNECTION_ABORT_REQUEST = 2151; // 0x867
+    field public static final int RRC_CONNECTION_ACCESS_BARRED = 2139; // 0x85b
+    field public static final int RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 2137; // 0x859
+    field public static final int RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 2138; // 0x85a
+    field public static final int RRC_CONNECTION_CELL_NOT_CAMPED = 2144; // 0x860
+    field public static final int RRC_CONNECTION_CELL_RESELECTION = 2140; // 0x85c
+    field public static final int RRC_CONNECTION_CONFIG_FAILURE = 2141; // 0x85d
+    field public static final int RRC_CONNECTION_INVALID_REQUEST = 2168; // 0x878
+    field public static final int RRC_CONNECTION_LINK_FAILURE = 2143; // 0x85f
+    field public static final int RRC_CONNECTION_NORMAL_RELEASE = 2147; // 0x863
+    field public static final int RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 2150; // 0x866
+    field public static final int RRC_CONNECTION_RADIO_LINK_FAILURE = 2148; // 0x864
+    field public static final int RRC_CONNECTION_REESTABLISHMENT_FAILURE = 2149; // 0x865
+    field public static final int RRC_CONNECTION_REJECT_BY_NETWORK = 2146; // 0x862
+    field public static final int RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 2172; // 0x87c
+    field public static final int RRC_CONNECTION_RF_UNAVAILABLE = 2170; // 0x87a
+    field public static final int RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 2152; // 0x868
+    field public static final int RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 2145; // 0x861
+    field public static final int RRC_CONNECTION_TIMER_EXPIRED = 2142; // 0x85e
+    field public static final int RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 2169; // 0x879
+    field public static final int RRC_UPLINK_CONNECTION_RELEASE = 2134; // 0x856
+    field public static final int RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 2132; // 0x854
+    field public static final int RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 2133; // 0x855
+    field public static final int RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 2136; // 0x858
+    field public static final int RRC_UPLINK_RADIO_LINK_FAILURE = 2135; // 0x857
+    field public static final int RUIM_NOT_PRESENT = 2085; // 0x825
+    field public static final int SECURITY_MODE_REJECTED = 2186; // 0x88a
+    field public static final int SERVICE_NOT_ALLOWED_ON_PLMN = 2129; // 0x851
     field public static final int SERVICE_OPTION_NOT_SUBSCRIBED = 33; // 0x21
     field public static final int SERVICE_OPTION_NOT_SUPPORTED = 32; // 0x20
     field public static final int SERVICE_OPTION_OUT_OF_ORDER = 34; // 0x22
     field public static final int SIGNAL_LOST = -3; // 0xfffffffd
+    field public static final int SIM_CARD_CHANGED = 2043; // 0x7fb
+    field public static final int SYNCHRONIZATION_FAILURE = 2184; // 0x888
+    field public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196; // 0x894
     field public static final int TETHERED_CALL_ACTIVE = -6; // 0xfffffffa
     field public static final int TFT_SEMANTIC_ERROR = 41; // 0x29
     field public static final int TFT_SYTAX_ERROR = 42; // 0x2a
+    field public static final int THERMAL_EMERGENCY = 2090; // 0x82a
+    field public static final int THERMAL_MITIGATION = 2062; // 0x80e
+    field public static final int TRAT_SWAP_FAILED = 2048; // 0x800
+    field public static final int UE_INITIATED_DETACH_OR_DISCONNECT = 128; // 0x80
+    field public static final int UE_IS_ENTERING_POWERSAVE_MODE = 2226; // 0x8b2
+    field public static final int UE_RAT_CHANGE = 2105; // 0x839
+    field public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 2185; // 0x889
+    field public static final int UMTS_HANDOVER_TO_IWLAN = 2199; // 0x897
     field public static final int UMTS_REACTIVATION_REQ = 39; // 0x27
+    field public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187; // 0x88b
     field public static final int UNKNOWN = 65536; // 0x10000
     field public static final int UNKNOWN_INFO_ELEMENT = 99; // 0x63
     field public static final int UNKNOWN_PDP_ADDRESS_TYPE = 28; // 0x1c
     field public static final int UNKNOWN_PDP_CONTEXT = 43; // 0x2b
+    field public static final int UNPREFERRED_RAT = 2039; // 0x7f7
+    field public static final int UNSUPPORTED_1X_PREV = 2214; // 0x8a6
     field public static final int UNSUPPORTED_APN_IN_CURRENT_PLMN = 66; // 0x42
+    field public static final int UNSUPPORTED_QCI_VALUE = 59; // 0x3b
     field public static final int USER_AUTHENTICATION = 29; // 0x1d
+    field public static final int VSNCP_ADMINISTRATIVELY_PROHIBITED = 2245; // 0x8c5
+    field public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be
+    field public static final int VSNCP_GEN_ERROR = 2237; // 0x8bd
+    field public static final int VSNCP_INSUFFICIENT_PARAMETERS = 2243; // 0x8c3
+    field public static final int VSNCP_NO_PDN_GATEWAY_ADDRESS = 2240; // 0x8c0
+    field public static final int VSNCP_PDN_EXISTS_FOR_THIS_APN = 2248; // 0x8c8
+    field public static final int VSNCP_PDN_GATEWAY_REJECT = 2242; // 0x8c2
+    field public static final int VSNCP_PDN_GATEWAY_UNREACHABLE = 2241; // 0x8c1
+    field public static final int VSNCP_PDN_ID_IN_USE = 2246; // 0x8c6
+    field public static final int VSNCP_PDN_LIMIT_EXCEEDED = 2239; // 0x8bf
+    field public static final int VSNCP_RECONNECT_NOT_ALLOWED = 2249; // 0x8c9
+    field public static final int VSNCP_RESOURCE_UNAVAILABLE = 2244; // 0x8c4
+    field public static final int VSNCP_SUBSCRIBER_LIMITATION = 2247; // 0x8c7
+    field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc
   }
 
   public class DisconnectCause {
@@ -8639,6 +8906,22 @@
 
 package android.util {
 
+  public class DocumentsStatsLog {
+    method public static void logActivityLaunch(int, boolean, int, int);
+    method public static void logFileOperation(int, int);
+    method public static void logFileOperationCanceled(int);
+    method public static void logFileOperationCopyMoveMode(int, int);
+    method public static void logFileOperationFailure(int, int);
+    method public static void logFilePick(int, long, int, boolean, int, int, int);
+    method public static void logInvalidScopedAccessRequest(int);
+    method public static void logPickerLaunchedFrom(String);
+    method public static void logRootVisited(int, int);
+    method public static void logSearchMode(int);
+    method public static void logSearchType(int);
+    method public static void logStartupMs(int);
+    method public static void logUserAction(int);
+  }
+
   public class EventLog {
     method public static void readEventsOnWrapping(int[], long, java.util.Collection<android.util.EventLog.Event>) throws java.io.IOException;
   }
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 79ef2ca..961a2c9 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -202,6 +202,7 @@
         NfcHceTransactionOccurred nfc_hce_transaction_occurred = 139;
         SeStateChanged se_state_changed = 140;
         SeOmapiReported se_omapi_reported = 141;
+        BroadcastDispatchLatencyReported broadcast_dispatch_latency_reported = 142;
     }
 
     // Pulled events will start at field 10000.
@@ -252,6 +253,7 @@
         ProcessMemoryHighWaterMark process_memory_high_water_mark = 10042;
         BatteryLevel battery_level = 10043;
         BuildInformation build_information = 10044;
+        BatteryCycleCount battery_cycle_count = 10045;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -2522,6 +2524,19 @@
     optional int32 time_to_inactive_secs = 5;
 };
 
+/**
+ * Logs total effective full charge and discharge cycles on a battery.
+ * Here are some examples of one effective cycle:
+ *   1) the battery charges from 0% to 100% and drains back to 0%,
+ *   2) charging from 50% to 100% and draining back to 50% twice.
+ * Pulled from:
+ *   frameworks/base/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
+ */
+message BatteryCycleCount {
+    /* Number of total charge and discharge cycles on the system battery. */
+    optional int32 cycle_count = 1;
+}
+
 /*
  * Logs when a connection becomes available and lost.
  * Logged in StatsCompanionService.java
@@ -4452,3 +4467,13 @@
 
   optional string packageName = 3;
 }
+
+/**
+  * Logs the dispatch latencey of a broadcast during processing of BOOT_COMPLETED.
+  * The dispatch latencey is the dispatchClockTime - enqueueClockTime.
+  * Logged from:
+  *   frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
+  */
+message BroadcastDispatchLatencyReported {
+  optional int64 dispatch_latency_millis = 1;
+}
diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
index b878652..75b63f4 100644
--- a/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
+++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.cpp
@@ -24,16 +24,16 @@
 
 #include "ResourceHealthManagerPuller.h"
 #include "logd/LogEvent.h"
-#include "statslog.h"
 #include "stats_log_util.h"
+#include "statslog.h"
 
 using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
 using android::hardware::health::V2_0::get_health_service;
 using android::hardware::health::V2_0::HealthInfo;
 using android::hardware::health::V2_0::IHealth;
 using android::hardware::health::V2_0::Result;
-using android::hardware::Return;
-using android::hardware::Void;
 
 using std::make_shared;
 using std::shared_ptr;
@@ -75,35 +75,41 @@
         }
         if (mTagId == android::util::REMAINING_BATTERY_CAPACITY) {
             auto ptr = make_shared<LogEvent>(android::util::REMAINING_BATTERY_CAPACITY,
-                wallClockTimestampNs, elapsedTimestampNs);
+                                             wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(v.legacy.batteryChargeCounter);
             ptr->init();
             data->push_back(ptr);
         } else if (mTagId == android::util::FULL_BATTERY_CAPACITY) {
             auto ptr = make_shared<LogEvent>(android::util::FULL_BATTERY_CAPACITY,
-                wallClockTimestampNs, elapsedTimestampNs);
+                                             wallClockTimestampNs, elapsedTimestampNs);
             ptr->write(v.legacy.batteryFullCharge);
             ptr->init();
             data->push_back(ptr);
         } else if (mTagId == android::util::BATTERY_VOLTAGE) {
-            auto ptr = make_shared<LogEvent>(android::util::BATTERY_VOLTAGE,
-                wallClockTimestampNs, elapsedTimestampNs);
+            auto ptr = make_shared<LogEvent>(android::util::BATTERY_VOLTAGE, wallClockTimestampNs,
+                                             elapsedTimestampNs);
             ptr->write(v.legacy.batteryVoltage);
             ptr->init();
             data->push_back(ptr);
         } else if (mTagId == android::util::BATTERY_LEVEL) {
-                     auto ptr = make_shared<LogEvent>(android::util::BATTERY_LEVEL,
-                         wallClockTimestampNs, elapsedTimestampNs);
-                     ptr->write(v.legacy.batteryLevel);
-                     ptr->init();
-                     data->push_back(ptr);
+            auto ptr = make_shared<LogEvent>(android::util::BATTERY_LEVEL, wallClockTimestampNs,
+                                             elapsedTimestampNs);
+            ptr->write(v.legacy.batteryLevel);
+            ptr->init();
+            data->push_back(ptr);
+        } else if (mTagId == android::util::BATTERY_CYCLE_COUNT) {
+            auto ptr = make_shared<LogEvent>(android::util::BATTERY_CYCLE_COUNT,
+                                             wallClockTimestampNs, elapsedTimestampNs);
+            ptr->write(v.legacy.batteryCycleCount);
+            ptr->init();
+            data->push_back(ptr);
         } else {
             ALOGE("Unsupported tag in ResourceHealthManagerPuller: %d", mTagId);
         }
     });
     if (!result_success || !ret.isOk()) {
         ALOGE("getHealthHal() failed: health HAL service not available. Description: %s",
-                ret.description().c_str());
+              ret.description().c_str());
         if (!ret.isOk() && ret.isDeadObject()) {
             gHealthHal = nullptr;
         }
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 4a716cf..19a7389 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -131,9 +131,12 @@
         // battery_voltage
         {android::util::BATTERY_VOLTAGE,
          {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
-        // battery_voltage
+        // battery_level
         {android::util::BATTERY_LEVEL,
          {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
+        // battery_cycle_count
+        {android::util::BATTERY_CYCLE_COUNT,
+         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
         // process_memory_state
         {android::util::PROCESS_MEMORY_STATE,
          {.additiveFields = {4, 5, 6, 7, 8, 9},
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 3ec0db4..c2e441b 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -2768,6 +2768,11 @@
 HPLandroid/hardware/location/GeofenceHardwareService$1;->registerForMonitorStateChangeCallback(ILandroid/hardware/location/IGeofenceHardwareMonitorCallback;)Z
 HPLandroid/hardware/location/GeofenceHardwareService$1;->removeGeofence(II)Z
 HPLandroid/hardware/location/GeofenceHardwareService;->checkPermission(III)V
+HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub$Proxy;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
+HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
+HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IActivityRecognitionHardwareClient;
+HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
+HPLandroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
 HPLandroid/hardware/location/IContextHubCallback$Stub;->asBinder()Landroid/os/IBinder;
 HPLandroid/hardware/location/IContextHubCallback$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
 HPLandroid/hardware/location/IContextHubService$Stub$Proxy;->findNanoAppOnHub(ILandroid/hardware/location/NanoAppFilter;)[I
@@ -21777,6 +21782,7 @@
 HSPLandroid/hardware/input/TouchCalibration$1;-><init>()V
 HSPLandroid/hardware/input/TouchCalibration;-><init>()V
 HSPLandroid/hardware/input/TouchCalibration;->getAffineTransform()[F
+HSPLandroid/hardware/location/ActivityRecognitionHardware;->isSupported()Z
 HSPLandroid/hardware/location/ContextHubInfo$1;-><init>()V
 HSPLandroid/hardware/location/ContextHubInfo;-><init>(Landroid/hardware/contexthub/V1_0/ContextHub;)V
 HSPLandroid/hardware/location/ContextHubMessage$1;-><init>()V
@@ -21796,6 +21802,13 @@
 HSPLandroid/hardware/location/GeofenceHardwareService;-><init>()V
 HSPLandroid/hardware/location/GeofenceHardwareService;->onBind(Landroid/content/Intent;)Landroid/os/IBinder;
 HSPLandroid/hardware/location/GeofenceHardwareService;->onCreate()V
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->disableActivityEvent(Ljava/lang/String;I)Z
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->enableActivityEvent(Ljava/lang/String;IJ)Z
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->flush()Z
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->getSupportedActivities()[Ljava/lang/String;
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->isActivitySupported(Ljava/lang/String;)Z
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->registerSink(Landroid/hardware/location/IActivityRecognitionHardwareSink;)Z
+HSPLandroid/hardware/location/IActivityRecognitionHardware;->unregisterSink(Landroid/hardware/location/IActivityRecognitionHardwareSink;)Z
 HSPLandroid/hardware/location/IContextHubCallback$Stub$Proxy;->asBinder()Landroid/os/IBinder;
 HSPLandroid/hardware/location/IContextHubCallback$Stub$Proxy;->onMessageReceipt(IILandroid/hardware/location/ContextHubMessage;)V
 HSPLandroid/hardware/location/IContextHubCallback;->onMessageReceipt(IILandroid/hardware/location/ContextHubMessage;)V
@@ -55637,6 +55650,7 @@
 Landroid/hardware/input/KeyboardLayout$1;
 Landroid/hardware/input/TouchCalibration$1;
 Landroid/hardware/input/TouchCalibration;
+Landroid/hardware/location/ActivityRecognitionHardware;
 Landroid/hardware/location/ContextHubInfo$1;
 Landroid/hardware/location/ContextHubInfo;
 Landroid/hardware/location/ContextHubManager;
@@ -55652,6 +55666,11 @@
 Landroid/hardware/location/GeofenceHardwareRequestParcelable$1;
 Landroid/hardware/location/GeofenceHardwareService$1;
 Landroid/hardware/location/GeofenceHardwareService;
+Landroid/hardware/location/IActivityRecognitionHardware$Stub;
+Landroid/hardware/location/IActivityRecognitionHardware;
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub$Proxy;
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;
+Landroid/hardware/location/IActivityRecognitionHardwareClient;
 Landroid/hardware/location/IContextHubCallback$Stub$Proxy;
 Landroid/hardware/location/IContextHubCallback;
 Landroid/hardware/location/IContextHubClient$Stub;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 3a4d904..fc47f67 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -462,6 +462,8 @@
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
 Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
+Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
+Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
diff --git a/config/preloaded-classes b/config/preloaded-classes
index cd798ad..c8a2a9c 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1405,7 +1405,10 @@
 android.hardware.input.InputManager$InputDeviceListener
 android.hardware.input.InputManager$InputDeviceListenerDelegate
 android.hardware.input.InputManager$InputDevicesChangedListener
+android.hardware.location.ActivityRecognitionHardware
 android.hardware.location.ContextHubManager
+android.hardware.location.IActivityRecognitionHardware
+android.hardware.location.IActivityRecognitionHardware$Stub
 android.hardware.radio.RadioManager
 android.hardware.soundtrigger.SoundTrigger
 android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 836627e..1063be4 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,6 +74,7 @@
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.StrictMode;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.os.UserHandle;
 import android.text.Selection;
 import android.text.SpannableStringBuilder;
@@ -1049,33 +1050,56 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface ContentCaptureNotificationType{}
 
-
-    private void notifyContentCaptureManagerIfNeeded(@ContentCaptureNotificationType int type) {
-        final ContentCaptureManager cm = getContentCaptureManager();
-        if (cm == null) return;
-
+    private String getContentCaptureTypeAsString(@ContentCaptureNotificationType int type) {
         switch (type) {
             case CONTENT_CAPTURE_START:
-                //TODO(b/111276913): decide whether the InteractionSessionId should be
-                // saved / restored in the activity bundle - probably not
-                int flags = 0;
-                if ((getWindow().getAttributes().flags
-                        & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
-                    flags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
-                }
-                cm.onActivityStarted(mToken, getComponentName(), flags);
-                break;
+                return "START";
             case CONTENT_CAPTURE_PAUSE:
-                cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_PAUSED);
-                break;
+                return "PAUSE";
             case CONTENT_CAPTURE_RESUME:
-                cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_RESUMED);
-                break;
+                return "RESUME";
             case CONTENT_CAPTURE_STOP:
-                cm.onActivityStopped();
-                break;
+                return "STOP";
             default:
-                Log.wtf(TAG, "Invalid @ContentCaptureNotificationType: " + type);
+                return "UNKNOW-" + type;
+        }
+    }
+
+    private void notifyContentCaptureManagerIfNeeded(@ContentCaptureNotificationType int type) {
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                    "notifyContentCapture(" + getContentCaptureTypeAsString(type) + ") for "
+                            + mComponent.toShortString());
+        }
+        try {
+            final ContentCaptureManager cm = getContentCaptureManager();
+            if (cm == null) return;
+
+            switch (type) {
+                case CONTENT_CAPTURE_START:
+                    //TODO(b/111276913): decide whether the InteractionSessionId should be
+                    // saved / restored in the activity bundle - probably not
+                    int flags = 0;
+                    if ((getWindow().getAttributes().flags
+                            & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+                        flags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
+                    }
+                    cm.onActivityStarted(mToken, getComponentName(), flags);
+                    break;
+                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();
+                    break;
+                default:
+                    Log.wtf(TAG, "Invalid @ContentCaptureNotificationType: " + type);
+            }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
         }
     }
 
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 1622c06..853b45e 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1324,7 +1324,8 @@
      * @param description the description that would appear for this file in Downloads App.
      * @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files
      * scanned by MediaScanner appear in the applications used to view media (for example,
-     * Gallery app).
+     * Gallery app). Starting from {@link android.os.Build.VERSION_CODES#Q}, this argument is
+     * ignored and the file is always scanned by MediaScanner.
      * @param mimeType mimetype of the file.
      * @param path absolute pathname to the file. The file should be world-readable, so that it can
      * be managed by the Downloads App and any other app that is used to read it (for example,
@@ -1353,7 +1354,8 @@
      * @param description the description that would appear for this file in Downloads App.
      * @param isMediaScannerScannable true if the file is to be scanned by MediaScanner. Files
      * scanned by MediaScanner appear in the applications used to view media (for example,
-     * Gallery app).
+     * Gallery app). Starting from {@link android.os.Build.VERSION_CODES#Q}, this argument is
+     * ignored and the file is always scanned by MediaScanner.
      * @param mimeType mimetype of the file.
      * @param path absolute pathname to the file. The file should be world-readable, so that it can
      * be managed by the Downloads App and any other app that is used to read it (for example,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index cefc700..280f1ac 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -771,7 +771,9 @@
      * <p>
      * This is not generally intended for third party application developers.
      */
-    public abstract String getOpPackageName();
+    public String getOpPackageName() {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
 
     /** Return the full application info for this context's package. */
     public abstract ApplicationInfo getApplicationInfo();
@@ -2980,9 +2982,11 @@
      *
      * @see #bindService
      */
-    public abstract boolean bindIsolatedService(@RequiresPermission Intent service,
+    public boolean bindIsolatedService(@RequiresPermission Intent service,
             @NonNull ServiceConnection conn, @BindServiceFlags int flags,
-            @NonNull String instanceName);
+            @NonNull String instanceName) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
 
     /**
      * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
@@ -3037,8 +3041,10 @@
      *                   a related groups -- higher importance values will be killed before
      *                   lower ones.
      */
-    public abstract void updateServiceGroup(@NonNull ServiceConnection conn, int group,
-            int importance);
+    public void updateServiceGroup(@NonNull ServiceConnection conn, int group,
+            int importance) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
 
     /**
      * Disconnect from an application service.  You will no longer receive
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8497656..3c487a1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3192,7 +3192,18 @@
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
+     *
+     * <p class="note">If the user has chosen a {@link android.telecom.CallRedirectionService} to
+     * handle redirection of outgoing calls, this intent will NOT be sent as an ordered broadcast.
+     * This means that attempts to re-write the outgoing call by other apps using this intent will
+     * be ignored.
+     * </p>
+     *
+     * @deprecated Apps that redirect outgoing calls should use the
+     * {@link android.telecom.CallRedirectionService} API.  Apps that perform call screening
+     * should use the {@link android.telecom.CallScreeningService} API.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_NEW_OUTGOING_CALL =
             "android.intent.action.NEW_OUTGOING_CALL";
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index 70a9f08..fa335c8b 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -17,6 +17,7 @@
 package android.hardware.display;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
@@ -30,6 +31,9 @@
 
 import com.android.internal.R;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Manages the display's color transforms and modes.
  *
@@ -39,6 +43,44 @@
 @SystemService(Context.COLOR_DISPLAY_SERVICE)
 public final class ColorDisplayManager {
 
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({CAPABILITY_NONE, CAPABILITY_PROTECTED_CONTENT, CAPABILITY_HARDWARE_ACCELERATION_GLOBAL,
+            CAPABILITY_HARDWARE_ACCELERATION_PER_APP})
+    public @interface CapabilityType {}
+
+    /**
+     * The device does not support color transforms.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CAPABILITY_NONE = 0x0;
+    /**
+     * The device can properly apply transforms over protected content.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CAPABILITY_PROTECTED_CONTENT = 0x1;
+    /**
+     * The device's hardware can efficiently apply transforms to the entire display.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CAPABILITY_HARDWARE_ACCELERATION_GLOBAL = 0x2;
+    /**
+     * The device's hardware can efficiently apply transforms to a specific Surface (window) so
+     * that apps can be transformed independently of one another.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int CAPABILITY_HARDWARE_ACCELERATION_PER_APP = 0x4;
+
     private final ColorDisplayManagerInternal mManager;
 
     /**
@@ -114,6 +156,17 @@
         return context.getResources().getBoolean(R.bool.config_setColorTransformAccelerated);
     }
 
+    /**
+     * Returns the available software and hardware color transform capabilities of this device.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+    public @CapabilityType int getTransformCapabilities() {
+        return mManager.getTransformCapabilities();
+    }
+
     private static class ColorDisplayManagerInternal {
 
         private static ColorDisplayManagerInternal sInstance;
@@ -162,5 +215,13 @@
                 throw e.rethrowFromSystemServer();
             }
         }
+
+        int getTransformCapabilities() {
+            try {
+                return mCdm.getTransformCapabilities();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
     }
 }
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 644f510..53cb8db 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -22,4 +22,6 @@
 
     boolean setSaturationLevel(int saturationLevel);
     boolean setAppSaturationLevel(String packageName, int saturationLevel);
+
+    int getTransformCapabilities();
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/hdmi/HdmiUtils.java b/core/java/android/hardware/hdmi/HdmiUtils.java
index 3081738..8c94b78 100644
--- a/core/java/android/hardware/hdmi/HdmiUtils.java
+++ b/core/java/android/hardware/hdmi/HdmiUtils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -16,14 +16,18 @@
 
 package android.hardware.hdmi;
 
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
- * Various utilities to handle HDMI CEC messages.
+ * Various utilities related to HDMI CEC.
  *
  * TODO(b/110094868): unhide for Q
  * @hide
  */
-public class HdmiUtils {
-
+public final class HdmiUtils {
     /**
      * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)}
      */
@@ -78,4 +82,164 @@
         }
         return port;
     }
+
+    /**
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HDMI_RELATIVE_POSITION_UNKNOWN, HDMI_RELATIVE_POSITION_DIRECTLY_BELOW,
+            HDMI_RELATIVE_POSITION_BELOW, HDMI_RELATIVE_POSITION_SAME,
+            HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE, HDMI_RELATIVE_POSITION_ABOVE,
+            HDMI_RELATIVE_POSITION_SIBLING, HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH})
+    public @interface HdmiAddressRelativePosition {}
+    /**
+     * HDMI relative position is not determined.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_UNKNOWN = 0;
+    /**
+     * HDMI relative position: directly blow the device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_DIRECTLY_BELOW = 1;
+    /**
+     * HDMI relative position: indirectly below the device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_BELOW = 2;
+    /**
+     * HDMI relative position: the same device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_SAME = 3;
+    /**
+     * HDMI relative position: directly above the device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE = 4;
+    /**
+     * HDMI relative position: indirectly above the device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_ABOVE = 5;
+    /**
+     * HDMI relative position: directly below a same device.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_SIBLING = 6;
+    /**
+     * HDMI relative position: different branch.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    public static final int HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH = 7;
+
+    private static final int NPOS = -1;
+
+    /**
+     * Check if the given physical address is valid.
+     *
+     * @param address physical address
+     * @return {@code true} if the given address is valid
+     */
+    public static boolean isValidPhysicalAddress(int address) {
+        if (address < 0 || address >= 0xFFFF) {
+            return false;
+        }
+        int mask = 0xF000;
+        boolean hasZero = false;
+        for (int i = 0; i < 4; i++) {
+            if ((address & mask) == 0) {
+                hasZero = true;
+            } else if (hasZero) {
+                // only 0s are valid after a 0.
+                // e.g. 0x1012 is not valid.
+                return false;
+            }
+            mask >>= 4;
+        }
+        return true;
+    }
+
+
+    /**
+     * Returns the relative position of two physical addresses.
+     */
+    @HdmiAddressRelativePosition
+    public static int getHdmiAddressRelativePosition(int src, int dest) {
+        if (src == 0xFFFF || dest == 0xFFFF) {
+            // address not assigned
+            return HDMI_RELATIVE_POSITION_UNKNOWN;
+        }
+        try {
+            int firstDiffPos = physicalAddressFirstDifferentDigitPos(src, dest);
+            if (firstDiffPos == NPOS) {
+                return HDMI_RELATIVE_POSITION_SAME;
+            }
+            int mask = (0xF000 >> (firstDiffPos * 4));
+            int nextPos = firstDiffPos + 1;
+            if ((src & mask) == 0) {
+                // src is above dest
+                if (nextPos == 4) {
+                    // last digits are different
+                    return HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE;
+                }
+                if (((0xF000 >> (nextPos * 4)) & dest) == 0) {
+                    // next digit is 0
+                    return HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE;
+                }
+                return HDMI_RELATIVE_POSITION_ABOVE;
+            }
+
+            if ((dest & mask) == 0) {
+                // src is below dest
+                if (nextPos == 4) {
+                    // last digits are different
+                    return HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
+                }
+                if (((0xF000 >> (nextPos * 4)) & src) == 0) {
+                    // next digit is 0
+                    return HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
+                }
+                return HDMI_RELATIVE_POSITION_BELOW;
+            }
+            if (nextPos == 4) {
+                // last digits are different
+                return HDMI_RELATIVE_POSITION_SIBLING;
+            }
+            if (((0xF000 >> (nextPos * 4)) & src) == 0 && ((0xF000 >> (nextPos * 4)) & dest) == 0) {
+                return HDMI_RELATIVE_POSITION_SIBLING;
+            }
+            return HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH;
+        } catch (IllegalArgumentException e) {
+            // invalid address
+            return HDMI_RELATIVE_POSITION_UNKNOWN;
+        }
+    }
+
+    private static int physicalAddressFirstDifferentDigitPos(int address1, int address2)
+            throws IllegalArgumentException {
+        if (!isValidPhysicalAddress(address1)) {
+            throw new IllegalArgumentException(address1 + " is not a valid address.");
+        }
+        if (!isValidPhysicalAddress(address2)) {
+            throw new IllegalArgumentException(address2 + " is not a valid address.");
+        }
+        int mask = 0xF000;
+        for (int i = 0; i < 4; i++) {
+            if ((address1 & mask) != (address2 & mask)) {
+                return i;
+            }
+            mask = mask >> 4;
+        }
+        return NPOS;
+    }
 }
diff --git a/core/java/android/hardware/location/ActivityChangedEvent.aidl b/core/java/android/hardware/location/ActivityChangedEvent.aidl
new file mode 100644
index 0000000..21f2445
--- /dev/null
+++ b/core/java/android/hardware/location/ActivityChangedEvent.aidl
@@ -0,0 +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.hardware.location;
+
+parcelable ActivityChangedEvent;
\ No newline at end of file
diff --git a/core/java/android/hardware/location/ActivityChangedEvent.java b/core/java/android/hardware/location/ActivityChangedEvent.java
new file mode 100644
index 0000000..16cfe6e
--- /dev/null
+++ b/core/java/android/hardware/location/ActivityChangedEvent.java
@@ -0,0 +1,92 @@
+/*
+ * 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.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A class representing an event for Activity changes.
+ *
+ * @hide
+ */
+public class ActivityChangedEvent implements Parcelable {
+    private final List<ActivityRecognitionEvent> mActivityRecognitionEvents;
+
+    public ActivityChangedEvent(ActivityRecognitionEvent[] activityRecognitionEvents) {
+        if (activityRecognitionEvents == null) {
+            throw new InvalidParameterException(
+                    "Parameter 'activityRecognitionEvents' must not be null.");
+        }
+
+        mActivityRecognitionEvents = Arrays.asList(activityRecognitionEvents);
+    }
+
+    @NonNull
+    public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() {
+        return mActivityRecognitionEvents;
+    }
+
+    public static final Creator<ActivityChangedEvent> CREATOR =
+            new Creator<ActivityChangedEvent>() {
+        @Override
+        public ActivityChangedEvent createFromParcel(Parcel source) {
+            int activityRecognitionEventsLength = source.readInt();
+            ActivityRecognitionEvent[] activityRecognitionEvents =
+                    new ActivityRecognitionEvent[activityRecognitionEventsLength];
+            source.readTypedArray(activityRecognitionEvents, ActivityRecognitionEvent.CREATOR);
+
+            return new ActivityChangedEvent(activityRecognitionEvents);
+        }
+
+        @Override
+        public ActivityChangedEvent[] newArray(int size) {
+            return new ActivityChangedEvent[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        ActivityRecognitionEvent[] activityRecognitionEventArray =
+                mActivityRecognitionEvents.toArray(new ActivityRecognitionEvent[0]);
+        parcel.writeInt(activityRecognitionEventArray.length);
+        parcel.writeTypedArray(activityRecognitionEventArray, flags);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("[ ActivityChangedEvent:");
+
+        for (ActivityRecognitionEvent event : mActivityRecognitionEvents) {
+            builder.append("\n    ");
+            builder.append(event.toString());
+        }
+        builder.append("\n]");
+
+        return builder.toString();
+    }
+}
diff --git a/core/java/android/hardware/location/ActivityRecognitionEvent.java b/core/java/android/hardware/location/ActivityRecognitionEvent.java
new file mode 100644
index 0000000..190030a
--- /dev/null
+++ b/core/java/android/hardware/location/ActivityRecognitionEvent.java
@@ -0,0 +1,87 @@
+/*
+ * 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.location;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents an Activity Recognition Event.
+ *
+ * @hide
+ */
+public class ActivityRecognitionEvent implements Parcelable {
+    private final String mActivity;
+    private final int mEventType;
+    private final long mTimestampNs;
+
+    public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) {
+        mActivity = activity;
+        mEventType = eventType;
+        mTimestampNs = timestampNs;
+    }
+
+    public String getActivity() {
+        return mActivity;
+    }
+
+    public int getEventType() {
+        return mEventType;
+    }
+
+    public long getTimestampNs() {
+        return mTimestampNs;
+    }
+
+    public static final Creator<ActivityRecognitionEvent> CREATOR =
+            new Creator<ActivityRecognitionEvent>() {
+        @Override
+        public ActivityRecognitionEvent createFromParcel(Parcel source) {
+            String activity = source.readString();
+            int eventType = source.readInt();
+            long timestampNs = source.readLong();
+
+            return new ActivityRecognitionEvent(activity, eventType, timestampNs);
+        }
+
+        @Override
+        public ActivityRecognitionEvent[] newArray(int size) {
+            return new ActivityRecognitionEvent[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mActivity);
+        parcel.writeInt(mEventType);
+        parcel.writeLong(mTimestampNs);
+    }
+
+    @Override
+    public String toString() {
+        return String.format(
+                "Activity='%s', EventType=%s, TimestampNs=%s",
+                mActivity,
+                mEventType,
+                mTimestampNs);
+    }
+}
diff --git a/core/java/android/hardware/location/ActivityRecognitionHardware.java b/core/java/android/hardware/location/ActivityRecognitionHardware.java
new file mode 100644
index 0000000..8acd1ff
--- /dev/null
+++ b/core/java/android/hardware/location/ActivityRecognitionHardware.java
@@ -0,0 +1,279 @@
+/*
+ * 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.location;
+
+import android.Manifest;
+import android.content.Context;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * A class that implements an {@link IActivityRecognitionHardware} backed up by the Activity
+ * Recognition HAL.
+ *
+ * @hide
+ */
+public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
+    private static final String TAG = "ActivityRecognitionHW";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware";
+
+    private static final int INVALID_ACTIVITY_TYPE = -1;
+    private static final int NATIVE_SUCCESS_RESULT = 0;
+    private static final int EVENT_TYPE_DISABLED = 0;
+    private static final int EVENT_TYPE_ENABLED = 1;
+
+    /**
+     * Contains the number of supported Event Types.
+     *
+     * NOTE: increment this counter every time a new EVENT_TYPE_ is added to
+     *       com.android.location.provider.ActivityRecognitionProvider
+     */
+    private static final int EVENT_TYPE_COUNT = 3;
+
+    private static ActivityRecognitionHardware sSingletonInstance;
+    private static final Object sSingletonInstanceLock = new Object();
+
+    private final Context mContext;
+    private final int mSupportedActivitiesCount;
+    private final String[] mSupportedActivities;
+    private final int[][] mSupportedActivitiesEnabledEvents;
+    private final SinkList mSinks = new SinkList();
+
+    private static class Event {
+        public int activity;
+        public int type;
+        public long timestamp;
+    }
+
+    private ActivityRecognitionHardware(Context context) {
+        nativeInitialize();
+
+        mContext = context;
+        mSupportedActivities = fetchSupportedActivities();
+        mSupportedActivitiesCount = mSupportedActivities.length;
+        mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT];
+    }
+
+    public static ActivityRecognitionHardware getInstance(Context context) {
+        synchronized (sSingletonInstanceLock) {
+            if (sSingletonInstance == null) {
+                sSingletonInstance = new ActivityRecognitionHardware(context);
+            }
+
+            return sSingletonInstance;
+        }
+    }
+
+    public static boolean isSupported() {
+        return nativeIsSupported();
+    }
+
+    @Override
+    public String[] getSupportedActivities() {
+        checkPermissions();
+        return mSupportedActivities;
+    }
+
+    @Override
+    public boolean isActivitySupported(String activity) {
+        checkPermissions();
+        int activityType = getActivityType(activity);
+        return activityType != INVALID_ACTIVITY_TYPE;
+    }
+
+    @Override
+    public boolean registerSink(IActivityRecognitionHardwareSink sink) {
+        checkPermissions();
+        return mSinks.register(sink);
+    }
+
+    @Override
+    public boolean unregisterSink(IActivityRecognitionHardwareSink sink) {
+        checkPermissions();
+        return mSinks.unregister(sink);
+    }
+
+    @Override
+    public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) {
+        checkPermissions();
+
+        int activityType = getActivityType(activity);
+        if (activityType == INVALID_ACTIVITY_TYPE) {
+            return false;
+        }
+
+        int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean disableActivityEvent(String activity, int eventType) {
+        checkPermissions();
+
+        int activityType = getActivityType(activity);
+        if (activityType == INVALID_ACTIVITY_TYPE) {
+            return false;
+        }
+
+        int result = nativeDisableActivityEvent(activityType, eventType);
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean flush() {
+        checkPermissions();
+        int result = nativeFlush();
+        return result == NATIVE_SUCCESS_RESULT;
+    }
+
+    /**
+     * Called by the Activity-Recognition HAL.
+     */
+    private void onActivityChanged(Event[] events) {
+        if (events == null || events.length == 0) {
+            if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged.");
+            return;
+        }
+
+        int eventsLength = events.length;
+        ActivityRecognitionEvent activityRecognitionEventArray[] =
+                new ActivityRecognitionEvent[eventsLength];
+        for (int i = 0; i < eventsLength; ++i) {
+            Event event = events[i];
+            String activityName = getActivityName(event.activity);
+            activityRecognitionEventArray[i] =
+                    new ActivityRecognitionEvent(activityName, event.type, event.timestamp);
+        }
+        ActivityChangedEvent activityChangedEvent =
+                new ActivityChangedEvent(activityRecognitionEventArray);
+
+        int size = mSinks.beginBroadcast();
+        for (int i = 0; i < size; ++i) {
+            IActivityRecognitionHardwareSink sink = mSinks.getBroadcastItem(i);
+            try {
+                sink.onActivityChanged(activityChangedEvent);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error delivering activity changed event.", e);
+            }
+        }
+        mSinks.finishBroadcast();
+    }
+
+    private String getActivityName(int activityType) {
+        if (activityType < 0 || activityType >= mSupportedActivities.length) {
+            String message = String.format(
+                    "Invalid ActivityType: %d, SupportedActivities: %d",
+                    activityType,
+                    mSupportedActivities.length);
+            Log.e(TAG, message);
+            return null;
+        }
+
+        return mSupportedActivities[activityType];
+    }
+
+    private int getActivityType(String activity) {
+        if (TextUtils.isEmpty(activity)) {
+            return INVALID_ACTIVITY_TYPE;
+        }
+
+        int supportedActivitiesLength = mSupportedActivities.length;
+        for (int i = 0; i < supportedActivitiesLength; ++i) {
+            if (activity.equals(mSupportedActivities[i])) {
+                return i;
+            }
+        }
+
+        return INVALID_ACTIVITY_TYPE;
+    }
+
+    private void checkPermissions() {
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+    }
+
+    private String[] fetchSupportedActivities() {
+        String[] supportedActivities = nativeGetSupportedActivities();
+        if (supportedActivities != null) {
+            return supportedActivities;
+        }
+
+        return new String[0];
+    }
+
+    private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> {
+        @Override
+        public void onCallbackDied(IActivityRecognitionHardwareSink callback) {
+            int callbackCount = mSinks.getRegisteredCallbackCount();
+            if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount);
+            if (callbackCount != 0) {
+                return;
+            }
+            // currently there is only one client for this, so if all its sinks have died, we clean
+            // up after them, this ensures that the AR HAL is not out of sink
+            for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) {
+                for (int event = 0; event < EVENT_TYPE_COUNT; ++event) {
+                    disableActivityEventIfEnabled(activity, event);
+                }
+            }
+        }
+
+        private void disableActivityEventIfEnabled(int activityType, int eventType) {
+            if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) {
+                return;
+            }
+
+            int result = nativeDisableActivityEvent(activityType, eventType);
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            String message = String.format(
+                    "DisableActivityEvent: activityType=%d, eventType=%d, result=%d",
+                    activityType,
+                    eventType,
+                    result);
+            Log.e(TAG, message);
+        }
+    }
+
+    // native bindings
+    static { nativeClassInit(); }
+
+    private static native void nativeClassInit();
+    private static native boolean nativeIsSupported();
+
+    private native void nativeInitialize();
+    private native void nativeRelease();
+    private native String[] nativeGetSupportedActivities();
+    private native int nativeEnableActivityEvent(
+            int activityType,
+            int eventType,
+            long reportLatenceNs);
+    private native int nativeDisableActivityEvent(int activityType, int eventType);
+    private native int nativeFlush();
+}
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardware.aidl b/core/java/android/hardware/location/IActivityRecognitionHardware.aidl
new file mode 100644
index 0000000..bc6b183
--- /dev/null
+++ b/core/java/android/hardware/location/IActivityRecognitionHardware.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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/license/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.location;
+
+import android.hardware.location.IActivityRecognitionHardwareSink;
+
+/**
+ * Activity Recognition Hardware provider interface.
+ * This interface can be used to implement hardware based activity recognition.
+ *
+ * @hide
+ */
+interface IActivityRecognitionHardware {
+    /**
+     * Gets an array of supported activities by hardware.
+     */
+    String[] getSupportedActivities();
+
+    /**
+     * Returns true if the given activity is supported, false otherwise.
+     */
+    boolean isActivitySupported(in String activityType);
+
+    /**
+     * Registers a sink with Hardware Activity-Recognition.
+     */
+    boolean registerSink(in IActivityRecognitionHardwareSink sink);
+
+    /**
+     * Unregisters a sink with Hardware Activity-Recognition.
+     */
+    boolean unregisterSink(in IActivityRecognitionHardwareSink sink);
+
+    /**
+     * Enables tracking of a given activity/event type, if the activity is supported.
+     */
+    boolean enableActivityEvent(in String activityType, int eventType, long reportLatencyNs);
+
+    /**
+     * Disables tracking of a given activity/eventy type.
+     */
+    boolean disableActivityEvent(in String activityType, int eventType);
+
+    /**
+     * Requests hardware for all the activity events detected up to the given point in time.
+     */
+    boolean flush();
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
new file mode 100644
index 0000000..3fe645c
--- /dev/null
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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/license/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.location;
+
+import android.hardware.location.IActivityRecognitionHardware;
+
+/**
+ * Activity Recognition Hardware client interface.
+ * This interface can be used to receive interfaces to implementations of
+ * {@link IActivityRecognitionHardware}.
+ *
+ * @hide
+ */
+oneway interface IActivityRecognitionHardwareClient {
+    /**
+     * Hardware Activity-Recognition availability event.
+     *
+     * @param isSupported whether the platform has hardware support for the feature
+     * @param instance the available instance to provide access to the feature
+     */
+    void onAvailabilityChanged(in boolean isSupported, in IActivityRecognitionHardware instance);
+}
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl
new file mode 100644
index 0000000..21c8e87
--- /dev/null
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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/license/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.location;
+
+import android.hardware.location.ActivityChangedEvent;
+
+/**
+ * Activity Recognition Hardware provider Sink interface.
+ * This interface can be used to implement sinks to receive activity notifications.
+ *
+ * @hide
+ */
+interface IActivityRecognitionHardwareSink {
+    /**
+     * Activity changed event.
+     */
+    void onActivityChanged(in ActivityChangedEvent event);
+}
\ No newline at end of file
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl
new file mode 100644
index 0000000..12e3117
--- /dev/null
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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/license/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.location;
+
+import android.hardware.location.IActivityRecognitionHardware;
+
+/**
+ * Activity Recognition Hardware watcher. This interface can be used to receive interfaces to
+ * implementations of {@link IActivityRecognitionHardware}.
+ *
+ * @deprecated use {@link IActivityRecognitionHardwareClient} instead.
+
+ * @hide
+ */
+interface IActivityRecognitionHardwareWatcher {
+    /**
+     * Hardware Activity-Recognition availability event.
+     */
+    void onInstanceChanged(in IActivityRecognitionHardware instance);
+}
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index abc1cac..90dccb5 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -86,7 +86,16 @@
  * <p>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
  * SSL certificate and hostname checks for testing purposes.  This setting
  * requires root access.
+ *
+ * @deprecated This class has less error-prone replacements using standard APIs.  To create an
+ * {@code SSLSocket}, obtain an {@link SSLSocketFactory} from {@link SSLSocketFactory#getDefault()}
+ * or {@link javax.net.ssl.SSLContext#getSocketFactory()}.  To verify hostnames, pass
+ * {@code "HTTPS"} to
+ * {@link javax.net.ssl.SSLParameters#setEndpointIdentificationAlgorithm(String)}.  To enable ALPN,
+ * use {@link javax.net.ssl.SSLParameters#setApplicationProtocols(String[])}.  To enable SNI,
+ * use {@link javax.net.ssl.SSLParameters#setServerNames(java.util.List)}.
  */
+@Deprecated
 public class SSLCertificateSocketFactory extends SSLSocketFactory {
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private static final String TAG = "SSLCertificateSocketFactory";
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
index a4d5c6f..92fcbb6 100644
--- a/core/java/android/os/HandlerThread.java
+++ b/core/java/android/os/HandlerThread.java
@@ -20,8 +20,10 @@
 import android.annotation.Nullable;
 
 /**
- * Handy class for starting a new thread that has a looper. The looper can then be 
- * used to create handler classes. Note that start() must still be called.
+ * A {@link Thread} that has a {@link Looper}.
+ * The {@link Looper} can then be used to create {@link Handler}s.
+ * <p>
+ * Note that just like with a regular {@link Thread}, {@link #start()} must still be called.
  */
 public class HandlerThread extends Thread {
     int mPriority;
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index a7e6601..cd3efb4 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -94,6 +94,15 @@
     @SystemApi
     public static final String NAMESPACE_NETD_NATIVE = "netd_native";
 
+    /**
+     * Namespace for features related to the ExtServices Notification Assistant.
+     * These features are applied immediately.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_NOTIFICATION_ASSISTANT = "notification_assistant";
+
     private static final Object sLock = new Object();
     @GuardedBy("sLock")
     private static Map<OnPropertyChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index a323ed1..893a2ae 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -50,6 +50,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
+
 import dalvik.system.VMRuntime;
 
 import java.io.File;
@@ -1109,11 +1111,13 @@
     }
 
     /**
-     * Test if the given URI represents roots backed by {@link DocumentsProvider}.
+     * Test if the given URI represents all roots of the authority
+     * backed by {@link DocumentsProvider}.
      *
      * @see #buildRootsUri(String)
      */
-    public static boolean isRootsUri(Context context, @Nullable Uri uri) {
+    public static boolean isRootsUri(@NonNull Context context, @Nullable Uri uri) {
+        Preconditions.checkNotNull(context, "context can not be null");
         return isRootUri(context, uri, 1 /* pathSize */);
     }
 
@@ -1122,7 +1126,8 @@
      *
      * @see #buildRootUri(String, String)
      */
-    public static boolean isRootUri(Context context, @Nullable Uri uri) {
+    public static boolean isRootUri(@NonNull Context context, @Nullable Uri uri) {
+        Preconditions.checkNotNull(context, "context can not be null");
         return isRootUri(context, uri, 2 /* pathSize */);
     }
 
@@ -1215,6 +1220,7 @@
      * {@hide}
      */
     public static String getSearchDocumentsQuery(@NonNull Bundle bundle) {
+        Preconditions.checkNotNull(bundle, "bundle can not be null");
         return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
     }
 
@@ -1315,8 +1321,12 @@
      * @return if given document is a descendant of the given parent.
      * @see Root#FLAG_SUPPORTS_IS_CHILD
      */
-    public static boolean isChildDocument(ContentInterface content, Uri parentDocumentUri,
-            Uri childDocumentUri) throws FileNotFoundException {
+    public static boolean isChildDocument(@NonNull ContentInterface content,
+            @NonNull Uri parentDocumentUri, @NonNull Uri childDocumentUri)
+            throws FileNotFoundException {
+        Preconditions.checkNotNull(content, "content can not be null");
+        Preconditions.checkNotNull(parentDocumentUri, "parentDocumentUri can not be null");
+        Preconditions.checkNotNull(childDocumentUri, "childDocumentUri can not be null");
         try {
             final Bundle in = new Bundle();
             in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
@@ -1325,7 +1335,7 @@
             final Bundle out = content.call(parentDocumentUri.getAuthority(),
                     METHOD_IS_CHILD_DOCUMENT, null, in);
             if (out == null) {
-                throw new RemoteException("Failed to get a reponse from isChildDocument query.");
+                throw new RemoteException("Failed to get a response from isChildDocument query.");
             }
             if (!out.containsKey(DocumentsContract.EXTRA_RESULT)) {
                 throw new RemoteException("Response did not include result field..");
@@ -1559,8 +1569,10 @@
      * @param documentUri a Document URI
      * @return a Bundle of Bundles.
      */
-    public static Bundle getDocumentMetadata(ContentInterface content, Uri documentUri)
-            throws FileNotFoundException {
+    public static @Nullable Bundle getDocumentMetadata(@NonNull ContentInterface content,
+            @NonNull Uri documentUri) throws FileNotFoundException {
+        Preconditions.checkNotNull(content, "content can not be null");
+        Preconditions.checkNotNull(documentUri, "documentUri can not be null");
         try {
             final Bundle in = new Bundle();
             in.putParcelable(EXTRA_URI, documentUri);
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 70c84f8..d78442d 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -37,6 +37,7 @@
 
 import android.Manifest;
 import android.annotation.CallSuper;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AuthenticationRequiredException;
 import android.content.ClipDescription;
@@ -63,6 +64,8 @@
 import android.provider.DocumentsContract.Root;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
+
 import libcore.io.IoUtils;
 
 import java.io.FileNotFoundException;
@@ -693,8 +696,10 @@
      * @see DocumentsContract#EXTRA_ERROR
      */
     @SuppressWarnings("unused")
-    public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
-            throws FileNotFoundException {
+    public Cursor querySearchDocuments(@NonNull String rootId, @Nullable String[] projection,
+            @NonNull Bundle queryArgs) throws FileNotFoundException {
+        Preconditions.checkNotNull(rootId, "rootId can not be null");
+        Preconditions.checkNotNull(queryArgs, "queryArgs can not be null");
         return querySearchDocuments(rootId, DocumentsContract.getSearchDocumentsQuery(queryArgs),
                 projection);
     }
@@ -732,7 +737,7 @@
      * @return a Bundle of Bundles.
      * @see DocumentsContract#getDocumentMetadata(ContentResolver, Uri)
      */
-    public @Nullable Bundle getDocumentMetadata(String documentId)
+    public @Nullable Bundle getDocumentMetadata(@NonNull String documentId)
             throws FileNotFoundException {
         throw new UnsupportedOperationException("Metadata not supported");
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 516f49c..643c473 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3300,6 +3300,14 @@
         public static final int SCREEN_BRIGHTNESS_MODE_AUTOMATIC = 1;
 
         /**
+         * Control whether to enable adaptive sleep mode.
+         * @hide
+         */
+        public static final String ADAPTIVE_SLEEP = "adaptive_sleep";
+
+        private static final Validator ADAPTIVE_SLEEP_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
          * Control whether the process CPU usage meter should be shown.
          *
          * @deprecated This functionality is no longer available as of
@@ -4232,6 +4240,7 @@
             SCREEN_BRIGHTNESS_MODE,
             SCREEN_AUTO_BRIGHTNESS_ADJ,
             SCREEN_BRIGHTNESS_FOR_VR,
+            ADAPTIVE_SLEEP,
             VIBRATE_INPUT_DEVICES,
             MODE_RINGER_STREAMS_AFFECTED,
             TEXT_AUTO_REPLACE,
@@ -4307,6 +4316,7 @@
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS);
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_FOR_VR);
             PUBLIC_SETTINGS.add(SCREEN_BRIGHTNESS_MODE);
+            PUBLIC_SETTINGS.add(ADAPTIVE_SLEEP);
             PUBLIC_SETTINGS.add(MODE_RINGER_STREAMS_AFFECTED);
             PUBLIC_SETTINGS.add(MUTE_STREAMS_AFFECTED);
             PUBLIC_SETTINGS.add(VIBRATE_ON);
@@ -4411,6 +4421,7 @@
             VALIDATORS.put(SCREEN_OFF_TIMEOUT, SCREEN_OFF_TIMEOUT_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS_FOR_VR, SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR);
             VALIDATORS.put(SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_VALIDATOR);
+            VALIDATORS.put(ADAPTIVE_SLEEP, ADAPTIVE_SLEEP_VALIDATOR);
             VALIDATORS.put(MODE_RINGER_STREAMS_AFFECTED, MODE_RINGER_STREAMS_AFFECTED_VALIDATOR);
             VALIDATORS.put(MUTE_STREAMS_AFFECTED, MUTE_STREAMS_AFFECTED_VALIDATOR);
             VALIDATORS.put(VIBRATE_ON, VIBRATE_ON_VALIDATOR);
@@ -13917,11 +13928,12 @@
          * The following keys are supported:
          *
          * <pre>
-         * enabled                         (boolean)
-         * requires_targeting_p            (boolean)
-         * max_squeeze_remeasure_attempts  (int)
-         * edit_choices_before_sending     (boolean)
-         * show_in_heads_up                (boolean)
+         * enabled                           (boolean)
+         * requires_targeting_p              (boolean)
+         * max_squeeze_remeasure_attempts    (int)
+         * edit_choices_before_sending       (boolean)
+         * show_in_heads_up                  (boolean)
+         * min_num_system_generated_replies  (int)
          * </pre>
          * @see com.android.systemui.statusbar.policy.SmartReplyConstants
          * @hide
diff --git a/core/java/android/util/DocumentsStatsLog.java b/core/java/android/util/DocumentsStatsLog.java
new file mode 100644
index 0000000..f483944
--- /dev/null
+++ b/core/java/android/util/DocumentsStatsLog.java
@@ -0,0 +1,168 @@
+/*
+ * 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.util;
+
+import android.annotation.SystemApi;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsProvider;
+
+/**
+ * DocumentsStatsLog provides APIs to send DocumentsUI related events to statsd.
+ * @hide
+ */
+@SystemApi
+public class DocumentsStatsLog {
+
+    private DocumentsStatsLog() {}
+
+    /**
+     * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up.
+     *
+     * @param action action that launches DocumentsUI.
+     * @param hasInitialUri is DocumentsUI launched with
+     *                      {@link DocumentsContract#EXTRA_INITIAL_URI}.
+     * @param mimeType the requested mime type.
+     * @param rootUri the resolved rootUri, or {@code null} if the provider doesn't
+     *                support {@link DocumentsProvider#findDocumentPath(String, String)}
+     */
+    public static void logActivityLaunch(
+            int action, boolean hasInitialUri, int mimeType, int rootUri) {
+        StatsLog.write(StatsLog.DOCS_UI_LAUNCH_REPORTED, action, hasInitialUri, mimeType, rootUri);
+    }
+
+    /**
+     * Logs root visited event.
+     *
+     * @param scope whether it's in FILES or PICKER mode.
+     * @param root the root that user visited
+     */
+    public static void logRootVisited(int scope, int root) {
+        StatsLog.write(StatsLog.DOCS_UI_ROOT_VISITED, scope, root);
+    }
+
+    /**
+     * Logs file operation stats. Call this when a file operation has completed.
+     *
+     * @param provider whether it's system or external provider
+     * @param fileOp the file operation
+     */
+    public static void logFileOperation(int provider, int fileOp) {
+        StatsLog.write(StatsLog.DOCS_UI_PROVIDER_FILE_OP, provider, fileOp);
+    }
+
+    /**
+     * Logs file operation stats. Call this when a copy/move operation has completed with a specific
+     * mode.
+     *
+     * @param fileOp copy or move file operation
+     * @param mode the mode for copy and move operation
+     */
+    public static void logFileOperationCopyMoveMode(int fileOp, int mode) {
+        StatsLog.write(StatsLog.DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED, fileOp, mode);
+    }
+
+    /**
+     * Logs file sub operation stats. Call this when a file operation has failed.
+     *
+     * @param authority the authority of the source document
+     * @param subOp the sub-file operation
+     */
+    public static void logFileOperationFailure(int authority, int subOp) {
+        StatsLog.write(StatsLog.DOCS_UI_FILE_OP_FAILURE, authority, subOp);
+    }
+
+    /**
+     * Logs the cancellation of a file operation. Call this when a job is canceled
+     *
+     * @param fileOp the file operation.
+     */
+    public static void logFileOperationCanceled(int fileOp) {
+        StatsLog.write(StatsLog.DOCS_UI_FILE_OP_CANCELED, fileOp);
+    }
+
+    /**
+     * Logs startup time in milliseconds.
+     *
+     * @param startupMs
+     */
+    public static void logStartupMs(int startupMs) {
+        StatsLog.write(StatsLog.DOCS_UI_STARTUP_MS, startupMs);
+    }
+
+    /**
+     * Logs the action that was started by user.
+     *
+     * @param userAction
+     */
+    public static void logUserAction(int userAction) {
+        StatsLog.write(StatsLog.DOCS_UI_USER_ACTION_REPORTED, userAction);
+    }
+
+    /**
+     * Logs the invalid type when invalid scoped access is requested.
+     *
+     * @param type the type of invalid scoped access request.
+     */
+    public static void logInvalidScopedAccessRequest(int type) {
+        StatsLog.write(StatsLog.DOCS_UI_INVALID_SCOPED_ACCESS_REQUEST, type);
+    }
+
+    /**
+     * Logs the package name that launches docsui picker mode.
+     *
+     * @param packageName
+     */
+    public static void logPickerLaunchedFrom(String packageName) {
+        StatsLog.write(StatsLog.DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED, packageName);
+    }
+
+    /**
+     * Logs the search type.
+     *
+     * @param searchType
+     */
+    public static void logSearchType(int searchType) {
+        StatsLog.write(StatsLog.DOCS_UI_SEARCH_TYPE_REPORTED, searchType);
+    }
+
+    /**
+     * Logs the search mode.
+     *
+     * @param searchMode
+     */
+    public static void logSearchMode(int searchMode) {
+        StatsLog.write(StatsLog.DOCS_UI_SEARCH_MODE_REPORTED, searchMode);
+    }
+
+    /**
+     * Logs the pick result information.
+     *
+     * @param actionCount total user action count during pick process.
+     * @param duration total time spent on pick process.
+     * @param fileCount number of picked files.
+     * @param isSearching are the picked files found by search.
+     * @param root the root where the picked files located.
+     * @param mimeType the mime type of the picked file. Only for single-select case.
+     * @param repeatedlyPickTimes number of times that the file has been picked before. Only for
+     *                            single-select case.
+     */
+    public static void logFilePick(int actionCount, long duration, int fileCount,
+            boolean isSearching, int root, int mimeType, int repeatedlyPickTimes) {
+        StatsLog.write(StatsLog.DOCS_UI_PICK_RESULT_REPORTED, actionCount, duration, fileCount,
+                isSearching, root, mimeType, repeatedlyPickTimes);
+    }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2131e6d..2014ec2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8227,7 +8227,15 @@
      * </ul>
      */
     public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
-        onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+            Trace.traceBegin(Trace.TRACE_TAG_VIEW,
+                    "onProvideContentCaptureStructure() for " + getClass().getSimpleName());
+        }
+        try {
+            onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
     }
 
     /** @hide */
@@ -9017,6 +9025,18 @@
      * </ol>
      */
     private void notifyAppearedOrDisappearedForContentCaptureIfNeeded(boolean appeared) {
+        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+            Trace.traceBegin(Trace.TRACE_TAG_VIEW,
+                    "notifyContentCapture(" + appeared + ") for " + getClass().getSimpleName());
+        }
+        try {
+            notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(appeared);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
+    }
+
+    private void notifyAppearedOrDisappearedForContentCaptureIfNeededNoTrace(boolean appeared) {
         // First check if context has client, so it saves a service lookup when it doesn't
         if (!mContext.isContentCaptureSupported()) return;
 
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index c4aa1d7..a691a24 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -25,7 +25,13 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 /**
- * Log all the things.
+ * Writes sysui_multi_event records to the system event log.
+ *
+ * Prefer the methods write(LogMaker), or count() or histogram(). Replace legacy methods with
+ * their current equivalents when the opportunity arises.
+ *
+ * This class is a lightweight dependency barrier - it is cheap and easy to construct.
+ * Logging is also cheap, so it is not normally necessary to move logging off of the UI thread.
  *
  * @hide
  */
@@ -52,6 +58,7 @@
     public static final int VIEW_UNKNOWN = MetricsEvent.VIEW_UNKNOWN;
     public static final int LOGTAG = EventLogTags.SYSUI_MULTI_ACTION;
 
+    /** Write an event log record, consisting of content.serialize(). */
     @UnsupportedAppUsage
     public void write(LogMaker content) {
         if (content.getType() == MetricsEvent.TYPE_UNKNOWN) {
@@ -60,128 +67,145 @@
         saveLog(content);
     }
 
+    /** Add an integer value to the monotonically increasing counter with the given name. */
+    public void count(String name, int value) {
+        saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
+                .setCounterName(name)
+                .setCounterValue(value));
+    }
+
+    /** Increment the bucket with the integer label on the histogram with the given name. */
+    public void histogram(String name, int bucket) {
+        // see LogHistogram in system/core/libmetricslogger/metrics_logger.cpp
+        saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
+                .setCounterName(name)
+                .setCounterBucket(bucket)
+                .setCounterValue(1));
+    }
+
+    /* Legacy logging methods follow.  These are all simple shorthands and can be replaced
+     * with an equivalent write(). */
+
+    /** Logs an OPEN event on the category.
+     *  Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_OPEN)) */
     public void visible(int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
             throw new IllegalArgumentException("Must define metric category");
         }
-        EventLogTags.writeSysuiViewVisibility(category, 100);
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_OPEN));
     }
 
+    /** Logs a CLOSE event on the category.
+     *  Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_CLOSE)) */
     public void hidden(int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
             throw new IllegalArgumentException("Must define metric category");
         }
-        EventLogTags.writeSysuiViewVisibility(category, 0);
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_CLOSE));
     }
 
-    public void visibility(int category, boolean visibile)
+    /** Logs an OPEN or CLOSE event on the category, depending on visible.
+     *  Equivalent to write(new LogMaker(category)
+     *                     .setType(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)) */
+    public void visibility(int category, boolean visible)
             throws IllegalArgumentException {
-        if (visibile) {
+        if (visible) {
             visible(category);
         } else {
             hidden(category);
         }
     }
 
+    /** Logs an OPEN or CLOSE event on the category, depending on vis.
+     *  Equivalent to write(new LogMaker(category)
+                           .setType(vis == View.VISIBLE ?
+                                    MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)) */
     public void visibility(int category, int vis)
             throws IllegalArgumentException {
         visibility(category, vis == View.VISIBLE);
     }
 
+    /** Logs an ACTION event on the category.
+     * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)) */
     public void action(int category) {
-        EventLogTags.writeSysuiAction(category, "");
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION));
     }
 
+    /** Logs an ACTION event on the category.
+     * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)
+                           .setSubtype(value) */
     public void action(int category, int value) {
-        EventLogTags.writeSysuiAction(category, Integer.toString(value));
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setSubtype(value));
     }
 
+    /** Logs an ACTION event on the category.
+     * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)
+                           .setSubtype(value ? 1 : 0) */
     public void action(int category, boolean value) {
-        EventLogTags.writeSysuiAction(category, Boolean.toString(value));
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setSubtype(value ? 1 : 0));
     }
 
+    /** Logs an ACTION event on the category.
+     * Equivalent to write(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION)
+                           .setPackageName(value ? 1 : 0) */
     public void action(int category, String pkg) {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
             throw new IllegalArgumentException("Must define metric category");
         }
-        EventLogTags.writeSysuiAction(category, pkg);
         saveLog(new LogMaker(category).setType(MetricsEvent.TYPE_ACTION).setPackageName(pkg));
     }
 
-    /** Add an integer value to the monotonically increasing counter with the given name. */
-    public void count(String name, int value) {
-        EventLogTags.writeSysuiCount(name, value);
-        saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_COUNTER)
-                    .setCounterName(name)
-                    .setCounterValue(value));
-    }
-
-    /** Increment the bucket with the integer label on the histogram with the given name. */
-    public void histogram(String name, int bucket) {
-        // see LogHistogram in system/core/libmetricslogger/metrics_logger.cpp
-        EventLogTags.writeSysuiHistogram(name, bucket);
-        saveLog(new LogMaker(MetricsEvent.RESERVED_FOR_LOGBUILDER_HISTOGRAM)
-                    .setCounterName(name)
-                    .setCounterBucket(bucket)
-                    .setCounterValue(1));
-    }
-
-    /** @deprecated use {@link #visible(int)} */
+    /** @deprecated because untestable; use {@link #visible(int)} */
     @Deprecated
     public static void visible(Context context, int category) throws IllegalArgumentException {
         getLogger().visible(category);
     }
 
-    /** @deprecated use {@link #hidden(int)} */
+    /** @deprecated because untestable; use {@link #hidden(int)} */
     @Deprecated
     public static void hidden(Context context, int category) throws IllegalArgumentException {
         getLogger().hidden(category);
     }
 
-    /** @deprecated use {@link #visibility(int, boolean)} */
+    /** @deprecated because untestable; use {@link #visibility(int, boolean)} */
     @Deprecated
     public static void visibility(Context context, int category, boolean visibile)
             throws IllegalArgumentException {
         getLogger().visibility(category, visibile);
     }
 
-    /** @deprecated use {@link #visibility(int, int)} */
+    /** @deprecated because untestable; use {@link #visibility(int, int)} */
     @Deprecated
     public static void visibility(Context context, int category, int vis)
             throws IllegalArgumentException {
         visibility(context, category, vis == View.VISIBLE);
     }
 
-    /** @deprecated use {@link #action(int)} */
+    /** @deprecated because untestable; use {@link #action(int)} */
     @Deprecated
     public static void action(Context context, int category) {
         getLogger().action(category);
     }
 
-    /** @deprecated use {@link #action(int, int)} */
+    /** @deprecated because untestable; use {@link #action(int, int)} */
     @Deprecated
     public static void action(Context context, int category, int value) {
         getLogger().action(category, value);
     }
 
-    /** @deprecated use {@link #action(int, boolean)} */
+    /** @deprecated because untestable; use {@link #action(int, boolean)} */
     @Deprecated
     public static void action(Context context, int category, boolean value) {
         getLogger().action(category, value);
     }
 
-    /** @deprecated use {@link #write(LogMaker)} */
+    /** @deprecated because untestable; use {@link #write(LogMaker)} */
     @Deprecated
     public static void action(LogMaker content) {
         getLogger().write(content);
     }
 
-    /** @deprecated use {@link #action(int, String)} */
+    /** @deprecated because untestable; use {@link #action(int, String)} */
     @Deprecated
     public static void action(Context context, int category, String pkg) {
         getLogger().action(category, pkg);
@@ -189,7 +213,7 @@
 
     /**
      * Add an integer value to the monotonically increasing counter with the given name.
-     * @deprecated use {@link #count(String, int)}
+     * @deprecated because untestable; use {@link #count(String, int)}
      */
     @Deprecated
     public static void count(Context context, String name, int value) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 17cc6af..534361e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,6 +87,10 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.location.gnssmetrics.GnssMetrics;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
@@ -187,18 +191,19 @@
     private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
 
     @VisibleForTesting
-    protected KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
+    protected KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
+            new KernelCpuUidUserSysTimeReader(true);
     @VisibleForTesting
     protected KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
     @VisibleForTesting
-    protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
-            new KernelUidCpuFreqTimeReader();
+    protected KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
+            new KernelCpuUidFreqTimeReader(true);
     @VisibleForTesting
-    protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
-            new KernelUidCpuActiveTimeReader();
+    protected KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
+            new KernelCpuUidActiveTimeReader(true);
     @VisibleForTesting
-    protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
-            new KernelUidCpuClusterTimeReader();
+    protected KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
+            new KernelCpuUidClusterTimeReader(true);
     @VisibleForTesting
     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
 
@@ -248,9 +253,9 @@
     /** Last time that RPM stats were updated by updateRpmStatsLocked. */
     private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
     /**
-     * Use a queue to delay removing UIDs from {@link KernelUidCpuTimeReader},
-     * {@link KernelUidCpuActiveTimeReader}, {@link KernelUidCpuClusterTimeReader},
-     * {@link KernelUidCpuFreqTimeReader} and from the Kernel.
+     * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader},
+     * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader},
+     * {@link KernelCpuUidFreqTimeReader} and from the Kernel.
      *
      * Isolated and invalid UID info must be removed to conserve memory. However, STATSD and
      * Batterystats both need to access UID cpu time. To resolve this race condition, only
@@ -281,22 +286,22 @@
 
         void remove() {
             if (startUid == endUid) {
-                mKernelUidCpuTimeReader.removeUid(startUid);
-                mKernelUidCpuFreqTimeReader.removeUid(startUid);
+                mCpuUidUserSysTimeReader.removeUid(startUid);
+                mCpuUidFreqTimeReader.removeUid(startUid);
                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
-                    mKernelUidCpuActiveTimeReader.removeUid(startUid);
-                    mKernelUidCpuClusterTimeReader.removeUid(startUid);
+                    mCpuUidActiveTimeReader.removeUid(startUid);
+                    mCpuUidClusterTimeReader.removeUid(startUid);
                 }
                 if (mKernelSingleUidTimeReader != null) {
                     mKernelSingleUidTimeReader.removeUid(startUid);
                 }
                 mNumUidsRemoved++;
             } else if (startUid < endUid) {
-                mKernelUidCpuFreqTimeReader.removeUidsInRange(startUid, endUid);
-                mKernelUidCpuTimeReader.removeUidsInRange(startUid, endUid);
+                mCpuUidFreqTimeReader.removeUidsInRange(startUid, endUid);
+                mCpuUidUserSysTimeReader.removeUidsInRange(startUid, endUid);
                 if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
-                    mKernelUidCpuActiveTimeReader.removeUidsInRange(startUid, endUid);
-                    mKernelUidCpuClusterTimeReader.removeUidsInRange(startUid, endUid);
+                    mCpuUidActiveTimeReader.removeUidsInRange(startUid, endUid);
+                    mCpuUidClusterTimeReader.removeUidsInRange(startUid, endUid);
                 }
                 if (mKernelSingleUidTimeReader != null) {
                     mKernelSingleUidTimeReader.removeUidsInRange(startUid, endUid);
@@ -496,7 +501,7 @@
             }
 
             final SparseArray<long[]> allUidCpuFreqTimesMs =
-                    mKernelUidCpuFreqTimeReader.getAllUidCpuFreqTimeMs();
+                    mCpuUidFreqTimeReader.getAllUidCpuFreqTimeMs();
             // If the KernelSingleUidTimeReader has stale cpu times, then we shouldn't try to
             // compute deltas since it might result in mis-attributing cpu times to wrong states.
             if (mIsPerProcessStateCpuDataStale) {
@@ -553,16 +558,16 @@
                 return false;
             }
             if (mCpuFreqs == null) {
-                mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
+                mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
             }
             if (mCpuFreqs != null) {
                 mKernelSingleUidTimeReader = new KernelSingleUidTimeReader(mCpuFreqs.length);
             } else {
-                mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable();
+                mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable();
                 return false;
             }
         }
-        mPerProcStateCpuTimesAvailable = mKernelUidCpuFreqTimeReader.allUidTimesAvailable()
+        mPerProcStateCpuTimesAvailable = mCpuUidFreqTimeReader.allUidTimesAvailable()
                 && mKernelSingleUidTimeReader.singleUidCpuTimesAvailable();
         return true;
     }
@@ -11926,7 +11931,7 @@
         }
 
         if (mCpuFreqs == null) {
-            mCpuFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
+            mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
         }
 
         // Calculate the wakelocks we have to distribute amongst. The system is excluded as it is
@@ -11952,12 +11957,12 @@
         // When the battery is not on, we don't attribute the cpu times to any timers but we still
         // need to take the snapshots.
         if (!onBattery) {
-            mKernelUidCpuTimeReader.readDelta(null);
-            mKernelUidCpuFreqTimeReader.readDelta(null);
+            mCpuUidUserSysTimeReader.readDelta(null);
+            mCpuUidFreqTimeReader.readDelta(null);
             mNumAllUidCpuTimeReads += 2;
             if (mConstants.TRACK_CPU_ACTIVE_CLUSTER_TIME) {
-                mKernelUidCpuActiveTimeReader.readDelta(null);
-                mKernelUidCpuClusterTimeReader.readDelta(null);
+                mCpuUidActiveTimeReader.readDelta(null);
+                mCpuUidClusterTimeReader.readDelta(null);
                 mNumAllUidCpuTimeReads += 2;
             }
             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
@@ -11967,7 +11972,7 @@
         }
 
         mUserInfoProvider.refreshUserIds();
-        final SparseLongArray updatedUids = mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()
+        final SparseLongArray updatedUids = mCpuUidFreqTimeReader.perClusterTimesAvailable()
                 ? null : new SparseLongArray();
         readKernelUidCpuTimesLocked(partialTimersToConsider, updatedUids, onBattery);
         // updatedUids=null means /proc/uid_time_in_state provides snapshots of per-cluster cpu
@@ -12084,18 +12089,20 @@
         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
         final long startTimeMs = mClocks.uptimeMillis();
 
-        mKernelUidCpuTimeReader.readDelta((uid, userTimeUs, systemTimeUs) -> {
+        mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> {
+            long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
+
             uid = mapUid(uid);
             if (Process.isIsolated(uid)) {
                 // This could happen if the isolated uid mapping was removed before that process
                 // was actually killed.
-                mKernelUidCpuTimeReader.removeUid(uid);
+                mCpuUidUserSysTimeReader.removeUid(uid);
                 Slog.d(TAG, "Got readings for an isolated uid with no mapping: " + uid);
                 return;
             }
             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
                 Slog.d(TAG, "Got readings for an invalid user's uid " + uid);
-                mKernelUidCpuTimeReader.removeUid(uid);
+                mCpuUidUserSysTimeReader.removeUid(uid);
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
@@ -12189,21 +12196,21 @@
     public void readKernelUidCpuFreqTimesLocked(@Nullable ArrayList<StopwatchTimer> partialTimers,
             boolean onBattery, boolean onBatteryScreenOff) {
         final boolean perClusterTimesAvailable =
-                mKernelUidCpuFreqTimeReader.perClusterTimesAvailable();
+                mCpuUidFreqTimeReader.perClusterTimesAvailable();
         final int numWakelocks = partialTimers == null ? 0 : partialTimers.size();
         final int numClusters = mPowerProfile.getNumCpuClusters();
         mWakeLockAllocationsUs = null;
         final long startTimeMs = mClocks.uptimeMillis();
-        mKernelUidCpuFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
+        mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> {
             uid = mapUid(uid);
             if (Process.isIsolated(uid)) {
-                mKernelUidCpuFreqTimeReader.removeUid(uid);
+                mCpuUidFreqTimeReader.removeUid(uid);
                 Slog.d(TAG, "Got freq readings for an isolated uid with no mapping: " + uid);
                 return;
             }
             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
                 Slog.d(TAG, "Got freq readings for an invalid user's uid " + uid);
-                mKernelUidCpuFreqTimeReader.removeUid(uid);
+                mCpuUidFreqTimeReader.removeUid(uid);
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
@@ -12307,16 +12314,16 @@
     @VisibleForTesting
     public void readKernelUidCpuActiveTimesLocked(boolean onBattery) {
         final long startTimeMs = mClocks.uptimeMillis();
-        mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
+        mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> {
             uid = mapUid(uid);
             if (Process.isIsolated(uid)) {
-                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                mCpuUidActiveTimeReader.removeUid(uid);
                 Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
                 return;
             }
             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
                 Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
-                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                mCpuUidActiveTimeReader.removeUid(uid);
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
@@ -12336,16 +12343,16 @@
     @VisibleForTesting
     public void readKernelUidCpuClusterTimesLocked(boolean onBattery) {
         final long startTimeMs = mClocks.uptimeMillis();
-        mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
+        mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> {
             uid = mapUid(uid);
             if (Process.isIsolated(uid)) {
-                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                mCpuUidClusterTimeReader.removeUid(uid);
                 Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
                 return;
             }
             if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
                 Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
-                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                mCpuUidClusterTimeReader.removeUid(uid);
                 return;
             }
             final Uid u = getUidStatsLocked(uid);
@@ -13344,7 +13351,7 @@
         private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false;
         private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
         private static final long DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS = 5_000;
-        private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 10_000;
+        private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
         private static final long DEFAULT_UID_REMOVE_DELAY_MS = 5L * 60L * 1000L;
         private static final long DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS = 600_000;
         private static final long DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS = 300_000;
@@ -13357,7 +13364,9 @@
         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;
         public long PROC_STATE_CPU_TIMES_READ_DELAY_MS = DEFAULT_PROC_STATE_CPU_TIMES_READ_DELAY_MS;
-        public long KERNEL_UID_READERS_THROTTLE_TIME = DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME;
+        /* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
+         * update when startObserving. */
+        public long KERNEL_UID_READERS_THROTTLE_TIME;
         public long UID_REMOVE_DELAY_MS = DEFAULT_UID_REMOVE_DELAY_MS;
         public long EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS
                 = DEFAULT_EXTERNAL_STATS_COLLECTION_RATE_LIMIT_MS;
@@ -13464,11 +13473,11 @@
         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
             if (oldTimeMs != newTimeMs) {
-                mKernelUidCpuTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
-                mKernelUidCpuFreqTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
-                mKernelUidCpuActiveTimeReader.setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
-                mKernelUidCpuClusterTimeReader
-                        .setThrottleInterval(KERNEL_UID_READERS_THROTTLE_TIME);
+                mCpuUidUserSysTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
+                mCpuUidFreqTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
+                mCpuUidActiveTimeReader.setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
+                mCpuUidClusterTimeReader
+                        .setThrottle(KERNEL_UID_READERS_THROTTLE_TIME);
             }
         }
 
diff --git a/core/java/com/android/internal/os/KernelCpuProcReader.java b/core/java/com/android/internal/os/KernelCpuProcReader.java
deleted file mode 100644
index c233ea8..0000000
--- a/core/java/com/android/internal/os/KernelCpuProcReader.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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 android.os.StrictMode;
-import android.os.SystemClock;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-
-/**
- * Reads cpu time proc files with throttling (adjustable interval).
- *
- * KernelCpuProcReader is implemented as singletons for built-in kernel proc files. Get___Instance()
- * method will return corresponding reader instance. In order to prevent frequent GC,
- * KernelCpuProcReader reuses a {@link ByteBuffer} to store data read from proc files.
- *
- * A KernelCpuProcReader instance keeps an error counter. When the number of read errors within that
- * instance accumulates to 5, this instance will reject all further read requests.
- *
- * Each KernelCpuProcReader instance also has a throttler. Throttle interval can be adjusted via
- * {@link #setThrottleInterval(long)} method. Default throttle interval is 3000ms. If current
- * timestamp based on {@link SystemClock#elapsedRealtime()} is less than throttle interval from
- * the last read timestamp, {@link #readBytes()} will return previous result.
- *
- * A KernelCpuProcReader instance is thread-unsafe. Caller needs to hold a lock on this object while
- * accessing its instance methods or digesting the return values.
- */
-public class KernelCpuProcReader {
-    private static final String TAG = "KernelCpuProcReader";
-    private static final int ERROR_THRESHOLD = 5;
-    // Throttle interval in milliseconds
-    private static final long DEFAULT_THROTTLE_INTERVAL = 3000L;
-    private static final int MAX_BUFFER_SIZE = 1024 * 1024;
-    private static final String PROC_UID_FREQ_TIME = "/proc/uid_cpupower/time_in_state";
-    private static final String PROC_UID_ACTIVE_TIME = "/proc/uid_cpupower/concurrent_active_time";
-    private static final String PROC_UID_CLUSTER_TIME = "/proc/uid_cpupower/concurrent_policy_time";
-
-    private static final KernelCpuProcReader mFreqTimeReader = new KernelCpuProcReader(
-            PROC_UID_FREQ_TIME);
-    private static final KernelCpuProcReader mActiveTimeReader = new KernelCpuProcReader(
-            PROC_UID_ACTIVE_TIME);
-    private static final KernelCpuProcReader mClusterTimeReader = new KernelCpuProcReader(
-            PROC_UID_CLUSTER_TIME);
-
-    public static KernelCpuProcReader getFreqTimeReaderInstance() {
-        return mFreqTimeReader;
-    }
-
-    public static KernelCpuProcReader getActiveTimeReaderInstance() {
-        return mActiveTimeReader;
-    }
-
-    public static KernelCpuProcReader getClusterTimeReaderInstance() {
-        return mClusterTimeReader;
-    }
-
-    private int mErrors;
-    private long mThrottleInterval = DEFAULT_THROTTLE_INTERVAL;
-    private long mLastReadTime = Long.MIN_VALUE;
-    private final Path mProc;
-    private byte[] mBuffer = new byte[8 * 1024];
-    private int mContentSize;
-
-    @VisibleForTesting
-    public KernelCpuProcReader(String procFile) {
-        mProc = Paths.get(procFile);
-    }
-
-    /**
-     * Reads all bytes from the corresponding proc file.
-     *
-     * If elapsed time since last call to this method is less than the throttle interval, it will
-     * return previous result. When IOException accumulates to 5, it will always return null. This
-     * method is thread-unsafe, so is the return value. Caller needs to hold a lock on this
-     * object while calling this method and digesting its return value.
-     *
-     * @return a {@link ByteBuffer} containing all bytes from the proc file.
-     */
-    public ByteBuffer readBytes() {
-        if (mErrors >= ERROR_THRESHOLD) {
-            return null;
-        }
-        if (SystemClock.elapsedRealtime() < mLastReadTime + mThrottleInterval) {
-            if (mContentSize > 0) {
-                return ByteBuffer.wrap(mBuffer, 0, mContentSize).asReadOnlyBuffer()
-                        .order(ByteOrder.nativeOrder());
-            }
-            return null;
-        }
-        mLastReadTime = SystemClock.elapsedRealtime();
-        mContentSize = 0;
-        final int oldMask = StrictMode.allowThreadDiskReadsMask();
-        try (InputStream in = Files.newInputStream(mProc)) {
-            int numBytes = 0;
-            int curr;
-            while ((curr = in.read(mBuffer, numBytes, mBuffer.length - numBytes)) >= 0) {
-                numBytes += curr;
-                if (numBytes == mBuffer.length) {
-                    // Hit the limit. Resize mBuffer.
-                    if (mBuffer.length == MAX_BUFFER_SIZE) {
-                        mErrors++;
-                        Slog.e(TAG, "Proc file is too large: " + mProc);
-                        return null;
-                    }
-                    mBuffer = Arrays.copyOf(mBuffer,
-                            Math.min(mBuffer.length << 1, MAX_BUFFER_SIZE));
-                }
-            }
-            mContentSize = numBytes;
-            return ByteBuffer.wrap(mBuffer, 0, mContentSize).asReadOnlyBuffer()
-                    .order(ByteOrder.nativeOrder());
-        } catch (NoSuchFileException | FileNotFoundException e) {
-            // Happens when the kernel does not provide this file. Not a big issue. Just log it.
-            mErrors++;
-            Slog.w(TAG, "File not exist: " + mProc);
-        } catch (IOException e) {
-            mErrors++;
-            Slog.e(TAG, "Error reading: " + mProc, e);
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
-        }
-        return null;
-    }
-
-    /**
-     * Sets the throttle interval. Set to 0 will disable throttling. Thread-unsafe, holding a lock
-     * on this object is recommended.
-     *
-     * @param throttleInterval throttle interval in milliseconds
-     */
-    public void setThrottleInterval(long throttleInterval) {
-        if (throttleInterval >= 0) {
-            mThrottleInterval = throttleInterval;
-        }
-    }
-}
diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
index 7021b57..e6d044f 100644
--- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
@@ -177,6 +177,9 @@
      * The file contains a monotonically increasing count of time for a single boot. This class
      * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
      * delta.
+     *
+     * The second parameter of the callback is a long[] with 2 elements, [user time in us, system
+     * time in us].
      */
     public static class KernelCpuUidUserSysTimeReader extends KernelCpuUidTimeReader<long[]> {
         private static final String REMOVE_UID_PROC_FILE = "/proc/uid_cputime/remove_uid_range";
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index ad62852..3c43a11 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -16,7 +16,6 @@
 package com.android.internal.os;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
-import static com.android.internal.os.KernelUidCpuFreqTimeReader.UID_TIMES_PROC_FILE;
 
 import android.annotation.NonNull;
 import android.util.Slog;
@@ -34,11 +33,12 @@
 
 @VisibleForTesting(visibility = PACKAGE)
 public class KernelSingleUidTimeReader {
-    private final String TAG = KernelUidCpuFreqTimeReader.class.getName();
-    private final boolean DBG = false;
+    private static final String TAG = KernelSingleUidTimeReader.class.getName();
+    private static final boolean DBG = false;
 
-    private final String PROC_FILE_DIR = "/proc/uid/";
-    private final String PROC_FILE_NAME = "/time_in_state";
+    private static final String PROC_FILE_DIR = "/proc/uid/";
+    private static final String PROC_FILE_NAME = "/time_in_state";
+    private static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";
 
     @VisibleForTesting
     public static final int TOTAL_READ_ERROR_COUNT = 5;
diff --git a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
deleted file mode 100644
index bd8a67a..0000000
--- a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
+++ /dev/null
@@ -1,179 +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.internal.os;
-
-import android.annotation.Nullable;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.util.function.Consumer;
-
-/**
- * Reads binary proc file /proc/uid_cpupower/concurrent_active_time and reports CPU active time to
- * BatteryStats to compute {@link PowerProfile#POWER_CPU_ACTIVE}.
- *
- * concurrent_active_time is an array of u32's in the following format:
- * [n, uid0, time0a, time0b, ..., time0n,
- * uid1, time1a, time1b, ..., time1n,
- * uid2, time2a, time2b, ..., time2n, etc.]
- * where n is the total number of cpus (num_possible_cpus)
- * ...
- * timeXn means the CPU time that a UID X spent running concurrently with n other processes.
- * The file contains a monotonically increasing count of time for a single boot. This class
- * maintains the previous results of a call to {@link #readDelta} in order to provide a
- * proper delta.
- *
- * This class uses a throttler to reject any {@link #readDelta} call within
- * {@link #mThrottleInterval}. This is different from the throttler in {@link KernelCpuProcReader},
- * which has a shorter throttle interval and returns cached result from last read when the request
- * is throttled.
- *
- * This class is NOT thread-safe and NOT designed to be accessed by more than one caller since each
- * caller has its own view of delta.
- */
-public class KernelUidCpuActiveTimeReader extends
-        KernelUidCpuTimeReaderBase<KernelUidCpuActiveTimeReader.Callback> {
-    private static final String TAG = KernelUidCpuActiveTimeReader.class.getSimpleName();
-
-    private final KernelCpuProcReader mProcReader;
-    private SparseArray<Double> mLastUidCpuActiveTimeMs = new SparseArray<>();
-    private int mCores;
-
-    public interface Callback extends KernelUidCpuTimeReaderBase.Callback {
-        /**
-         * Notifies when new data is available.
-         *
-         * @param uid             uid int
-         * @param cpuActiveTimeMs cpu active time spent by this uid in milliseconds
-         */
-        void onUidCpuActiveTime(int uid, long cpuActiveTimeMs);
-    }
-
-    public KernelUidCpuActiveTimeReader() {
-        mProcReader = KernelCpuProcReader.getActiveTimeReaderInstance();
-    }
-
-    @VisibleForTesting
-    public KernelUidCpuActiveTimeReader(KernelCpuProcReader procReader) {
-        mProcReader = procReader;
-    }
-
-    @Override
-    protected void readDeltaImpl(@Nullable Callback callback) {
-        readImpl((buf) -> {
-            int uid = buf.get();
-            double activeTime = sumActiveTime(buf);
-            if (activeTime > 0) {
-                double delta = activeTime - mLastUidCpuActiveTimeMs.get(uid, 0.0);
-                if (delta > 0) {
-                    mLastUidCpuActiveTimeMs.put(uid, activeTime);
-                    if (callback != null) {
-                        callback.onUidCpuActiveTime(uid, (long) delta);
-                    }
-                } else if (delta < 0) {
-                    Slog.e(TAG, "Negative delta from active time proc: " + delta);
-                }
-            }
-        });
-    }
-
-    public void readAbsolute(Callback callback) {
-        readImpl((buf) -> {
-            int uid = buf.get();
-            double activeTime = sumActiveTime(buf);
-            if (activeTime > 0) {
-                callback.onUidCpuActiveTime(uid, (long) activeTime);
-            }
-        });
-    }
-
-    private double sumActiveTime(IntBuffer buffer) {
-        double sum = 0;
-        boolean corrupted = false;
-        for (int j = 1; j <= mCores; j++) {
-            int time = buffer.get();
-            if (time < 0) {
-                // Even if error happens, we still need to continue reading.
-                // Buffer cannot be skipped.
-                Slog.e(TAG, "Negative time from active time proc: " + time);
-                corrupted = true;
-            } else {
-                sum += (double) time * 10 / j; // Unit is 10ms.
-            }
-        }
-        return corrupted ? -1 : sum;
-    }
-
-    /**
-     * readImpl accepts a callback to process the uid entry. readDeltaImpl needs to store the last
-     * seen results while processing the buffer, while readAbsolute returns the absolute value read
-     * from the buffer without storing. So readImpl contains the common logic of the two, leaving
-     * the difference to a processUid function.
-     *
-     * @param processUid the callback function to process the uid entry in the buffer.
-     */
-    private void readImpl(Consumer<IntBuffer> processUid) {
-        synchronized (mProcReader) {
-            final ByteBuffer bytes = mProcReader.readBytes();
-            if (bytes == null || bytes.remaining() <= 4) {
-                // Error already logged in mProcReader.
-                return;
-            }
-            if ((bytes.remaining() & 3) != 0) {
-                Slog.wtf(TAG,
-                        "Cannot parse active time proc bytes to int: " + bytes.remaining());
-                return;
-            }
-            final IntBuffer buf = bytes.asIntBuffer();
-            final int cores = buf.get();
-            if (mCores != 0 && cores != mCores) {
-                Slog.wtf(TAG, "Cpu active time wrong # cores: " + cores);
-                return;
-            }
-            mCores = cores;
-            if (cores <= 0 || buf.remaining() % (cores + 1) != 0) {
-                Slog.wtf(TAG,
-                        "Cpu active time format error: " + buf.remaining() + " / " + (cores
-                                + 1));
-                return;
-            }
-            int numUids = buf.remaining() / (cores + 1);
-            for (int i = 0; i < numUids; i++) {
-                processUid.accept(buf);
-            }
-            if (DEBUG) {
-                Slog.d(TAG, "Read uids: " + numUids);
-            }
-        }
-    }
-
-    public void removeUid(int uid) {
-        mLastUidCpuActiveTimeMs.delete(uid);
-    }
-
-    public void removeUidsInRange(int startUid, int endUid) {
-        mLastUidCpuActiveTimeMs.put(startUid, null);
-        mLastUidCpuActiveTimeMs.put(endUid, null);
-        final int firstIndex = mLastUidCpuActiveTimeMs.indexOfKey(startUid);
-        final int lastIndex = mLastUidCpuActiveTimeMs.indexOfKey(endUid);
-        mLastUidCpuActiveTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
-    }
-}
diff --git a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
deleted file mode 100644
index 3cbfaea..0000000
--- a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
+++ /dev/null
@@ -1,239 +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.internal.os;
-
-import android.annotation.Nullable;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.util.function.Consumer;
-
-/**
- * Reads binary proc file /proc/uid_cpupower/concurrent_policy_time and reports CPU cluster times
- * to BatteryStats to compute cluster power. See
- * {@link PowerProfile#getAveragePowerForCpuCluster(int)}.
- *
- * concurrent_policy_time is an array of u32's in the following format:
- * [n, x0, ..., xn, uid0, time0a, time0b, ..., time0n,
- * uid1, time1a, time1b, ..., time1n,
- * uid2, time2a, time2b, ..., time2n, etc.]
- * where n is the number of policies
- * xi is the number cpus on a particular policy
- * Each uidX is followed by x0 time entries corresponding to the time UID X spent on cluster0
- * running concurrently with 0, 1, 2, ..., x0 - 1 other processes, then followed by x1, ..., xn
- * time entries.
- *
- * The file contains a monotonically increasing count of time for a single boot. This class
- * maintains the previous results of a call to {@link #readDelta} in order to provide a
- * proper delta.
- *
- * This class uses a throttler to reject any {@link #readDelta} call within
- * {@link #mThrottleInterval}. This is different from the throttler in {@link KernelCpuProcReader},
- * which has a shorter throttle interval and returns cached result from last read when the request
- * is throttled.
- *
- * This class is NOT thread-safe and NOT designed to be accessed by more than one caller since each
- * caller has its own view of delta.
- */
-public class KernelUidCpuClusterTimeReader extends
-        KernelUidCpuTimeReaderBase<KernelUidCpuClusterTimeReader.Callback> {
-    private static final String TAG = KernelUidCpuClusterTimeReader.class.getSimpleName();
-
-    private final KernelCpuProcReader mProcReader;
-    private SparseArray<double[]> mLastUidPolicyTimeMs = new SparseArray<>();
-
-    private int mNumClusters = -1;
-    private int mNumCores;
-    private int[] mNumCoresOnCluster;
-
-    private double[] mCurTime; // Reuse to avoid GC.
-    private long[] mDeltaTime; // Reuse to avoid GC.
-    private long[] mCurTimeRounded; // Reuse to avoid GC.
-
-    public interface Callback extends KernelUidCpuTimeReaderBase.Callback {
-        /**
-         * Notifies when new data is available.
-         *
-         * @param uid              uid int
-         * @param cpuClusterTimeMs an array of times spent by this uid on corresponding clusters.
-         *                         The array index is the cluster index.
-         */
-        void onUidCpuPolicyTime(int uid, long[] cpuClusterTimeMs);
-    }
-
-    public KernelUidCpuClusterTimeReader() {
-        mProcReader = KernelCpuProcReader.getClusterTimeReaderInstance();
-    }
-
-    @VisibleForTesting
-    public KernelUidCpuClusterTimeReader(KernelCpuProcReader procReader) {
-        mProcReader = procReader;
-    }
-
-    @Override
-    protected void readDeltaImpl(@Nullable Callback cb) {
-        readImpl((buf) -> {
-            int uid = buf.get();
-            double[] lastTimes = mLastUidPolicyTimeMs.get(uid);
-            if (lastTimes == null) {
-                lastTimes = new double[mNumClusters];
-                mLastUidPolicyTimeMs.put(uid, lastTimes);
-            }
-            if (!sumClusterTime(buf, mCurTime)) {
-                return;
-            }
-            boolean valid = true;
-            boolean notify = false;
-            for (int i = 0; i < mNumClusters; i++) {
-                mDeltaTime[i] = (long) (mCurTime[i] - lastTimes[i]);
-                if (mDeltaTime[i] < 0) {
-                    Slog.e(TAG, "Negative delta from cluster time proc: " + mDeltaTime[i]);
-                    valid = false;
-                }
-                notify |= mDeltaTime[i] > 0;
-            }
-            if (notify && valid) {
-                System.arraycopy(mCurTime, 0, lastTimes, 0, mNumClusters);
-                if (cb != null) {
-                    cb.onUidCpuPolicyTime(uid, mDeltaTime);
-                }
-            }
-        });
-    }
-
-    public void readAbsolute(Callback callback) {
-        readImpl((buf) -> {
-            int uid = buf.get();
-            if (sumClusterTime(buf, mCurTime)) {
-                for (int i = 0; i < mNumClusters; i++) {
-                    mCurTimeRounded[i] = (long) mCurTime[i];
-                }
-                callback.onUidCpuPolicyTime(uid, mCurTimeRounded);
-            }
-        });
-    }
-
-    private boolean sumClusterTime(IntBuffer buffer, double[] clusterTime) {
-        boolean valid = true;
-        for (int i = 0; i < mNumClusters; i++) {
-            clusterTime[i] = 0;
-            for (int j = 1; j <= mNumCoresOnCluster[i]; j++) {
-                int time = buffer.get();
-                if (time < 0) {
-                    Slog.e(TAG, "Negative time from cluster time proc: " + time);
-                    valid = false;
-                }
-                clusterTime[i] += (double) time * 10 / j; // Unit is 10ms.
-            }
-        }
-        return valid;
-    }
-
-    /**
-     * readImpl accepts a callback to process the uid entry. readDeltaImpl needs to store the last
-     * seen results while processing the buffer, while readAbsolute returns the absolute value read
-     * from the buffer without storing. So readImpl contains the common logic of the two, leaving
-     * the difference to a processUid function.
-     *
-     * @param processUid the callback function to process the uid entry in the buffer.
-     */
-    private void readImpl(Consumer<IntBuffer> processUid) {
-        synchronized (mProcReader) {
-            ByteBuffer bytes = mProcReader.readBytes();
-            if (bytes == null || bytes.remaining() <= 4) {
-                // Error already logged in mProcReader.
-                return;
-            }
-            if ((bytes.remaining() & 3) != 0) {
-                Slog.wtf(TAG,
-                        "Cannot parse cluster time proc bytes to int: " + bytes.remaining());
-                return;
-            }
-            IntBuffer buf = bytes.asIntBuffer();
-            final int numClusters = buf.get();
-            if (numClusters <= 0) {
-                Slog.wtf(TAG, "Cluster time format error: " + numClusters);
-                return;
-            }
-            if (mNumClusters == -1) {
-                mNumClusters = numClusters;
-            }
-            if (buf.remaining() < numClusters) {
-                Slog.wtf(TAG, "Too few data left in the buffer: " + buf.remaining());
-                return;
-            }
-            if (mNumCores <= 0) {
-                if (!readCoreInfo(buf, numClusters)) {
-                    return;
-                }
-            } else {
-                buf.position(buf.position() + numClusters);
-            }
-
-            if (buf.remaining() % (mNumCores + 1) != 0) {
-                Slog.wtf(TAG,
-                        "Cluster time format error: " + buf.remaining() + " / " + (mNumCores
-                                + 1));
-                return;
-            }
-            int numUids = buf.remaining() / (mNumCores + 1);
-
-            for (int i = 0; i < numUids; i++) {
-                processUid.accept(buf);
-            }
-            if (DEBUG) {
-                Slog.d(TAG, "Read uids: " + numUids);
-            }
-        }
-    }
-
-    // Returns if it has read valid info.
-    private boolean readCoreInfo(IntBuffer buf, int numClusters) {
-        int numCores = 0;
-        int[] numCoresOnCluster = new int[numClusters];
-        for (int i = 0; i < numClusters; i++) {
-            numCoresOnCluster[i] = buf.get();
-            numCores += numCoresOnCluster[i];
-        }
-        if (numCores <= 0) {
-            Slog.e(TAG, "Invalid # cores from cluster time proc file: " + numCores);
-            return false;
-        }
-        mNumCores = numCores;
-        mNumCoresOnCluster = numCoresOnCluster;
-        mCurTime = new double[numClusters];
-        mDeltaTime = new long[numClusters];
-        mCurTimeRounded = new long[numClusters];
-        return true;
-    }
-
-    public void removeUid(int uid) {
-        mLastUidPolicyTimeMs.delete(uid);
-    }
-
-    public void removeUidsInRange(int startUid, int endUid) {
-        mLastUidPolicyTimeMs.put(startUid, null);
-        mLastUidPolicyTimeMs.put(endUid, null);
-        final int firstIndex = mLastUidPolicyTimeMs.indexOfKey(startUid);
-        final int lastIndex = mLastUidPolicyTimeMs.indexOfKey(endUid);
-        mLastUidPolicyTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
-    }
-}
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
deleted file mode 100644
index 5b46d0f..0000000
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ /dev/null
@@ -1,296 +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.internal.os;
-
-import static com.android.internal.util.Preconditions.checkNotNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.StrictMode;
-import android.util.IntArray;
-import android.util.Slog;
-import android.util.SparseArray;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.util.function.Consumer;
-
-/**
- * Reads /proc/uid_time_in_state which has the format:
- *
- * uid: [freq1] [freq2] [freq3] ...
- * [uid1]: [time in freq1] [time in freq2] [time in freq3] ...
- * [uid2]: [time in freq1] [time in freq2] [time in freq3] ...
- * ...
- *
- * Binary variation reads /proc/uid_cpupower/time_in_state in the following format:
- * [n, uid0, time0a, time0b, ..., time0n,
- * uid1, time1a, time1b, ..., time1n,
- * uid2, time2a, time2b, ..., time2n, etc.]
- * where n is the total number of frequencies.
- *
- * This provides the times a UID's processes spent executing at each different cpu frequency.
- * The file contains a monotonically increasing count of time for a single boot. This class
- * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
- * delta.
- *
- * This class uses a throttler to reject any {@link #readDelta} call within
- * {@link #mThrottleInterval}. This is different from the throttler in {@link KernelCpuProcReader},
- * which has a shorter throttle interval and returns cached result from last read when the request
- * is throttled.
- *
- * This class is NOT thread-safe and NOT designed to be accessed by more than one caller since each
- * caller has its own view of delta.
- */
-public class KernelUidCpuFreqTimeReader extends
-        KernelUidCpuTimeReaderBase<KernelUidCpuFreqTimeReader.Callback> {
-    private static final String TAG = KernelUidCpuFreqTimeReader.class.getSimpleName();
-    static final String UID_TIMES_PROC_FILE = "/proc/uid_time_in_state";
-
-    public interface Callback extends KernelUidCpuTimeReaderBase.Callback {
-        void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs);
-    }
-
-    private long[] mCpuFreqs;
-    private long[] mCurTimes; // Reuse to prevent GC.
-    private long[] mDeltaTimes; // Reuse to prevent GC.
-    private int mCpuFreqsCount;
-    private final KernelCpuProcReader mProcReader;
-
-    private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
-
-    // We check the existence of proc file a few times (just in case it is not ready yet when we
-    // start reading) and if it is not available, we simply ignore further read requests.
-    private static final int TOTAL_READ_ERROR_COUNT = 5;
-    private int mReadErrorCounter;
-    private boolean mPerClusterTimesAvailable;
-    private boolean mAllUidTimesAvailable = true;
-
-    public KernelUidCpuFreqTimeReader() {
-        mProcReader = KernelCpuProcReader.getFreqTimeReaderInstance();
-    }
-
-    @VisibleForTesting
-    public KernelUidCpuFreqTimeReader(KernelCpuProcReader procReader) {
-        mProcReader = procReader;
-    }
-
-    public boolean perClusterTimesAvailable() {
-        return mPerClusterTimesAvailable;
-    }
-
-    public boolean allUidTimesAvailable() {
-        return mAllUidTimesAvailable;
-    }
-
-    public SparseArray<long[]> getAllUidCpuFreqTimeMs() {
-        return mLastUidCpuFreqTimeMs;
-    }
-
-    public long[] readFreqs(@NonNull PowerProfile powerProfile) {
-        checkNotNull(powerProfile);
-        if (mCpuFreqs != null) {
-            // No need to read cpu freqs more than once.
-            return mCpuFreqs;
-        }
-        if (!mAllUidTimesAvailable) {
-            return null;
-        }
-        final int oldMask = StrictMode.allowThreadDiskReadsMask();
-        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
-            return readFreqs(reader, powerProfile);
-        } catch (IOException e) {
-            if (++mReadErrorCounter >= TOTAL_READ_ERROR_COUNT) {
-                mAllUidTimesAvailable = false;
-            }
-            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
-            return null;
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
-        }
-    }
-
-    @VisibleForTesting
-    public long[] readFreqs(BufferedReader reader, PowerProfile powerProfile)
-            throws IOException {
-        final String line = reader.readLine();
-        if (line == null) {
-            return null;
-        }
-        final String[] freqStr = line.split(" ");
-        // First item would be "uid: " which needs to be ignored.
-        mCpuFreqsCount = freqStr.length - 1;
-        mCpuFreqs = new long[mCpuFreqsCount];
-        mCurTimes = new long[mCpuFreqsCount];
-        mDeltaTimes = new long[mCpuFreqsCount];
-        for (int i = 0; i < mCpuFreqsCount; ++i) {
-            mCpuFreqs[i] = Long.parseLong(freqStr[i + 1], 10);
-        }
-
-        // Check if the freqs in the proc file correspond to per-cluster freqs.
-        final IntArray numClusterFreqs = extractClusterInfoFromProcFileFreqs();
-        final int numClusters = powerProfile.getNumCpuClusters();
-        if (numClusterFreqs.size() == numClusters) {
-            mPerClusterTimesAvailable = true;
-            for (int i = 0; i < numClusters; ++i) {
-                if (numClusterFreqs.get(i) != powerProfile.getNumSpeedStepsInCpuCluster(i)) {
-                    mPerClusterTimesAvailable = false;
-                    break;
-                }
-            }
-        } else {
-            mPerClusterTimesAvailable = false;
-        }
-        Slog.i(TAG, "mPerClusterTimesAvailable=" + mPerClusterTimesAvailable);
-        return mCpuFreqs;
-    }
-
-    @Override
-    @VisibleForTesting
-    public void readDeltaImpl(@Nullable Callback callback) {
-        if (mCpuFreqs == null) {
-            return;
-        }
-        readImpl((buf) -> {
-            int uid = buf.get();
-            long[] lastTimes = mLastUidCpuFreqTimeMs.get(uid);
-            if (lastTimes == null) {
-                lastTimes = new long[mCpuFreqsCount];
-                mLastUidCpuFreqTimeMs.put(uid, lastTimes);
-            }
-            if (!getFreqTimeForUid(buf, mCurTimes)) {
-                return;
-            }
-            boolean notify = false;
-            boolean valid = true;
-            for (int i = 0; i < mCpuFreqsCount; i++) {
-                mDeltaTimes[i] = mCurTimes[i] - lastTimes[i];
-                if (mDeltaTimes[i] < 0) {
-                    Slog.e(TAG, "Negative delta from freq time proc: " + mDeltaTimes[i]);
-                    valid = false;
-                }
-                notify |= mDeltaTimes[i] > 0;
-            }
-            if (notify && valid) {
-                System.arraycopy(mCurTimes, 0, lastTimes, 0, mCpuFreqsCount);
-                if (callback != null) {
-                    callback.onUidCpuFreqTime(uid, mDeltaTimes);
-                }
-            }
-        });
-    }
-
-    public void readAbsolute(Callback callback) {
-        readImpl((buf) -> {
-            int uid = buf.get();
-            if (getFreqTimeForUid(buf, mCurTimes)) {
-                callback.onUidCpuFreqTime(uid, mCurTimes);
-            }
-        });
-    }
-
-    private boolean getFreqTimeForUid(IntBuffer buffer, long[] freqTime) {
-        boolean valid = true;
-        for (int i = 0; i < mCpuFreqsCount; i++) {
-            freqTime[i] = (long) buffer.get() * 10; // Unit is 10ms.
-            if (freqTime[i] < 0) {
-                Slog.e(TAG, "Negative time from freq time proc: " + freqTime[i]);
-                valid = false;
-            }
-        }
-        return valid;
-    }
-
-    /**
-     * readImpl accepts a callback to process the uid entry. readDeltaImpl needs to store the last
-     * seen results while processing the buffer, while readAbsolute returns the absolute value read
-     * from the buffer without storing. So readImpl contains the common logic of the two, leaving
-     * the difference to a processUid function.
-     *
-     * @param processUid the callback function to process the uid entry in the buffer.
-     */
-    private void readImpl(Consumer<IntBuffer> processUid) {
-        synchronized (mProcReader) {
-            ByteBuffer bytes = mProcReader.readBytes();
-            if (bytes == null || bytes.remaining() <= 4) {
-                // Error already logged in mProcReader.
-                return;
-            }
-            if ((bytes.remaining() & 3) != 0) {
-                Slog.wtf(TAG, "Cannot parse freq time proc bytes to int: " + bytes.remaining());
-                return;
-            }
-            IntBuffer buf = bytes.asIntBuffer();
-            final int freqs = buf.get();
-            if (freqs != mCpuFreqsCount) {
-                Slog.wtf(TAG, "Cpu freqs expect " + mCpuFreqsCount + " , got " + freqs);
-                return;
-            }
-            if (buf.remaining() % (freqs + 1) != 0) {
-                Slog.wtf(TAG, "Freq time format error: " + buf.remaining() + " / " + (freqs + 1));
-                return;
-            }
-            int numUids = buf.remaining() / (freqs + 1);
-            for (int i = 0; i < numUids; i++) {
-                processUid.accept(buf);
-            }
-            if (DEBUG) {
-                Slog.d(TAG, "Read uids: #" + numUids);
-            }
-        }
-    }
-
-    public void removeUid(int uid) {
-        mLastUidCpuFreqTimeMs.delete(uid);
-    }
-
-    public void removeUidsInRange(int startUid, int endUid) {
-        mLastUidCpuFreqTimeMs.put(startUid, null);
-        mLastUidCpuFreqTimeMs.put(endUid, null);
-        final int firstIndex = mLastUidCpuFreqTimeMs.indexOfKey(startUid);
-        final int lastIndex = mLastUidCpuFreqTimeMs.indexOfKey(endUid);
-        mLastUidCpuFreqTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
-    }
-
-    /**
-     * Extracts no. of cpu clusters and no. of freqs in each of these clusters from the freqs
-     * read from the proc file.
-     *
-     * We need to assume that freqs in each cluster are strictly increasing.
-     * For e.g. if the freqs read from proc file are: 12, 34, 15, 45, 12, 15, 52. Then it means
-     * there are 3 clusters: (12, 34), (15, 45), (12, 15, 52)
-     *
-     * @return an IntArray filled with no. of freqs in each cluster.
-     */
-    private IntArray extractClusterInfoFromProcFileFreqs() {
-        final IntArray numClusterFreqs = new IntArray();
-        int freqsFound = 0;
-        for (int i = 0; i < mCpuFreqsCount; ++i) {
-            freqsFound++;
-            if (i + 1 == mCpuFreqsCount || mCpuFreqs[i + 1] <= mCpuFreqs[i]) {
-                numClusterFreqs.add(freqsFound);
-                freqsFound = 0;
-            }
-        }
-        return numClusterFreqs;
-    }
-}
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
deleted file mode 100644
index 97b7211..0000000
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.os;
-
-import android.annotation.Nullable;
-import android.os.StrictMode;
-import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseLongArray;
-import android.util.TimeUtils;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-
-/**
- * Reads /proc/uid_cputime/show_uid_stat which has the line format:
- *
- * uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds
- *
- * This provides the time a UID's processes spent executing in user-space and kernel-space.
- * The file contains a monotonically increasing count of time for a single boot. This class
- * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
- * delta.
- */
-public class KernelUidCpuTimeReader extends
-        KernelUidCpuTimeReaderBase<KernelUidCpuTimeReader.Callback> {
-    private static final String TAG = KernelUidCpuTimeReader.class.getSimpleName();
-    private static final String sProcFile = "/proc/uid_cputime/show_uid_stat";
-    private static final String sRemoveUidProcFile = "/proc/uid_cputime/remove_uid_range";
-
-    /**
-     * Callback interface for processing each line of the proc file.
-     */
-    public interface Callback extends KernelUidCpuTimeReaderBase.Callback {
-        /**
-         * @param uid          UID of the app
-         * @param userTimeUs   time spent executing in user space in microseconds
-         * @param systemTimeUs time spent executing in kernel space in microseconds
-         */
-        void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs);
-    }
-
-    private SparseLongArray mLastUserTimeUs = new SparseLongArray();
-    private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
-    private long mLastTimeReadUs = 0;
-
-    /**
-     * Reads the proc file, calling into the callback with a delta of time for each UID.
-     *
-     * @param callback The callback to invoke for each line of the proc file. If null,
-     *                 the data is consumed and subsequent calls to readDelta will provide
-     *                 a fresh delta.
-     */
-    @Override
-    protected void readDeltaImpl(@Nullable Callback callback) {
-        final int oldMask = StrictMode.allowThreadDiskReadsMask();
-        long nowUs = SystemClock.elapsedRealtime() * 1000;
-        try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
-            TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
-            String line;
-            while ((line = reader.readLine()) != null) {
-                splitter.setString(line);
-                final String uidStr = splitter.next();
-                final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
-                final long userTimeUs = Long.parseLong(splitter.next(), 10);
-                final long systemTimeUs = Long.parseLong(splitter.next(), 10);
-
-                boolean notifyCallback = false;
-                long userTimeDeltaUs = userTimeUs;
-                long systemTimeDeltaUs = systemTimeUs;
-                // Only report if there is a callback and if this is not the first read.
-                if (callback != null && mLastTimeReadUs != 0) {
-                    int index = mLastUserTimeUs.indexOfKey(uid);
-                    if (index >= 0) {
-                        userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
-                        systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
-
-                        final long timeDiffUs = nowUs - mLastTimeReadUs;
-                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
-                            StringBuilder sb = new StringBuilder("Malformed cpu data for UID=");
-                            sb.append(uid).append("!\n");
-                            sb.append("Time between reads: ");
-                            TimeUtils.formatDuration(timeDiffUs / 1000, sb);
-                            sb.append("\n");
-                            sb.append("Previous times: u=");
-                            TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
-                            sb.append(" s=");
-                            TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
-
-                            sb.append("\nCurrent times: u=");
-                            TimeUtils.formatDuration(userTimeUs / 1000, sb);
-                            sb.append(" s=");
-                            TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append("\nDelta: u=");
-                            TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
-                            sb.append(" s=");
-                            TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
-                            Slog.e(TAG, sb.toString());
-
-                            userTimeDeltaUs = 0;
-                            systemTimeDeltaUs = 0;
-                        }
-                    }
-
-                    notifyCallback = (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0);
-                }
-                mLastUserTimeUs.put(uid, userTimeUs);
-                mLastSystemTimeUs.put(uid, systemTimeUs);
-                if (notifyCallback) {
-                    callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
-                }
-            }
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
-        }
-        mLastTimeReadUs = nowUs;
-    }
-
-    /**
-     * Reads the proc file, calling into the callback with raw absolute value of time for each UID.
-     * @param callback The callback to invoke for each line of the proc file.
-     */
-    public void readAbsolute(Callback callback) {
-        final int oldMask = StrictMode.allowThreadDiskReadsMask();
-        try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
-            TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
-            String line;
-            while ((line = reader.readLine()) != null) {
-                splitter.setString(line);
-                final String uidStr = splitter.next();
-                final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
-                final long userTimeUs = Long.parseLong(splitter.next(), 10);
-                final long systemTimeUs = Long.parseLong(splitter.next(), 10);
-                callback.onUidCpuTime(uid, userTimeUs, systemTimeUs);
-            }
-        } catch (IOException e) {
-            Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
-        }
-    }
-
-    /**
-     * Removes the UID from the kernel module and from internal accounting data. Only
-     * {@link BatteryStatsImpl} and its child processes should call this, as the change on Kernel is
-     * visible system wide.
-     *
-     * @param uid The UID to remove.
-     */
-    public void removeUid(int uid) {
-        final int index = mLastSystemTimeUs.indexOfKey(uid);
-        if (index >= 0) {
-            mLastSystemTimeUs.removeAt(index);
-            mLastUserTimeUs.removeAt(index);
-        }
-        removeUidsFromKernelModule(uid, uid);
-    }
-
-    /**
-     * Removes UIDs in a given range from the kernel module and internal accounting data. Only
-     * {@link BatteryStatsImpl} and its child processes should call this, as the change on Kernel is
-     * visible system wide.
-     *
-     * @param startUid the first uid to remove
-     * @param endUid   the last uid to remove
-     */
-    public void removeUidsInRange(int startUid, int endUid) {
-        if (endUid < startUid) {
-            return;
-        }
-        mLastSystemTimeUs.put(startUid, 0);
-        mLastUserTimeUs.put(startUid, 0);
-        mLastSystemTimeUs.put(endUid, 0);
-        mLastUserTimeUs.put(endUid, 0);
-        final int startIndex = mLastSystemTimeUs.indexOfKey(startUid);
-        final int endIndex = mLastSystemTimeUs.indexOfKey(endUid);
-        mLastSystemTimeUs.removeAtRange(startIndex, endIndex - startIndex + 1);
-        mLastUserTimeUs.removeAtRange(startIndex, endIndex - startIndex + 1);
-        removeUidsFromKernelModule(startUid, endUid);
-    }
-
-    private void removeUidsFromKernelModule(int startUid, int endUid) {
-        Slog.d(TAG, "Removing uids " + startUid + "-" + endUid);
-        final int oldMask = StrictMode.allowThreadDiskWritesMask();
-        try (FileWriter writer = new FileWriter(sRemoveUidProcFile)) {
-            writer.write(startUid + "-" + endUid);
-            writer.flush();
-        } catch (IOException e) {
-            Slog.e(TAG, "failed to remove uids " + startUid + " - " + endUid
-                    + " from uid_cputime module", e);
-        } finally {
-            StrictMode.setThreadPolicyMask(oldMask);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReaderBase.java b/core/java/com/android/internal/os/KernelUidCpuTimeReaderBase.java
deleted file mode 100644
index 11e50e1..0000000
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReaderBase.java
+++ /dev/null
@@ -1,60 +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.internal.os;
-
-import android.annotation.Nullable;
-import android.os.SystemClock;
-import android.util.Slog;
-
-/**
- * The base class of all KernelUidCpuTimeReaders.
- *
- * This class is NOT designed to be thread-safe or accessed by more than one caller (due to
- * the nature of {@link #readDelta(Callback)}).
- */
-public abstract class KernelUidCpuTimeReaderBase<T extends KernelUidCpuTimeReaderBase.Callback> {
-    protected static final boolean DEBUG = false;
-    // Throttle interval in milliseconds
-    private static final long DEFAULT_THROTTLE_INTERVAL = 10_000L;
-
-    private final String TAG = this.getClass().getSimpleName();
-    private long mLastTimeReadMs = Long.MIN_VALUE;
-    private long mThrottleInterval = DEFAULT_THROTTLE_INTERVAL;
-
-    // A generic Callback interface (used by readDelta) to be extended by subclasses.
-    public interface Callback {
-    }
-
-    public void readDelta(@Nullable T cb) {
-        if (SystemClock.elapsedRealtime() < mLastTimeReadMs + mThrottleInterval) {
-            if (DEBUG) {
-                Slog.d(TAG, "Throttle");
-            }
-            return;
-        }
-        readDeltaImpl(cb);
-        mLastTimeReadMs = SystemClock.elapsedRealtime();
-    }
-
-    protected abstract void readDeltaImpl(@Nullable T cb);
-
-    public void setThrottleInterval(long throttleInterval) {
-        if (throttleInterval >= 0) {
-            mThrottleInterval = throttleInterval;
-        }
-    }
-}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 197e873..d61f10e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -65,7 +65,7 @@
             int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);
     void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
             in NotificationVisibility[] noLongerVisibleKeys);
-    void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
+    void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded, in int notificationLocation);
     void onNotificationDirectReplied(String key);
     void onNotificationSmartSuggestionsAdded(String key, int smartReplyCount, int smartActionCount,
             boolean generatedByAsssistant);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index c5dfe6c..be12700 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -186,6 +186,7 @@
         "android_hardware_UsbDevice.cpp",
         "android_hardware_UsbDeviceConnection.cpp",
         "android_hardware_UsbRequest.cpp",
+        "android_hardware_location_ActivityRecognitionHardware.cpp",
         "android_util_FileObserver.cpp",
         "android/opengl/poly_clip.cpp", // TODO: .arm
         "android/opengl/util.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5befab9..18d9b5a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -101,6 +101,7 @@
 extern int register_android_hardware_UsbDevice(JNIEnv *env);
 extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
 extern int register_android_hardware_UsbRequest(JNIEnv *env);
+extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);
 
 extern int register_android_media_AudioEffectDescriptor(JNIEnv *env);
 extern int register_android_media_AudioRecord(JNIEnv *env);
@@ -1460,6 +1461,7 @@
     REG_JNI(register_android_hardware_UsbDevice),
     REG_JNI(register_android_hardware_UsbDeviceConnection),
     REG_JNI(register_android_hardware_UsbRequest),
+    REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
     REG_JNI(register_android_media_AudioEffectDescriptor),
     REG_JNI(register_android_media_AudioSystem),
     REG_JNI(register_android_media_AudioRecord),
diff --git a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
new file mode 100644
index 0000000..1c9ab94
--- /dev/null
+++ b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 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.
+ */
+
+#define LOG_TAG "ActivityRecognitionHardware"
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+
+// #include <hardware/activity_recognition.h>
+// The activity recognition HAL is being deprecated. This means -
+//    i) Android framework code shall not depend on activity recognition
+//       being provided through the activity_recognition.h interface.
+//   ii) activity recognition HAL will not be binderized as the other HALs.
+//
+
+/**
+ * Initializes the ActivityRecognitionHardware class from the native side.
+ */
+static void class_init(JNIEnv* /*env*/, jclass /*clazz*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+}
+
+/**
+ * Initializes and connect the callbacks handlers in the HAL.
+ */
+static void initialize(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+}
+
+/**
+ * De-initializes the ActivityRecognitionHardware from the native side.
+ */
+static void release(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+}
+
+/**
+ * Returns true if ActivityRecognition HAL is supported, false otherwise.
+ */
+static jboolean is_supported(JNIEnv* /*env*/, jclass /*clazz*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return JNI_FALSE;
+}
+
+/**
+ * Gets an array representing the supported activities.
+ */
+static jobjectArray get_supported_activities(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return NULL;
+}
+
+/**
+ * Enables a given activity event to be actively monitored.
+ */
+static int enable_activity_event(
+        JNIEnv* /*env*/,
+        jobject /*obj*/,
+        jint /*activity_handle*/,
+        jint /*event_type*/,
+        jlong /*report_latency_ns*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
+}
+
+/**
+ * Disables a given activity event from being actively monitored.
+ */
+static int disable_activity_event(
+        JNIEnv* /*env*/,
+        jobject /*obj*/,
+        jint /*activity_handle*/,
+        jint /*event_type*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
+}
+
+/**
+ * Request flush for al batch buffers.
+ */
+static int flush(JNIEnv* /*env*/, jobject /*obj*/) {
+    ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op",
+          __FUNCTION__);
+    return android::NO_INIT;
+}
+
+
+static const JNINativeMethod sMethods[] = {
+    // {"name", "signature", (void*) functionPointer },
+    { "nativeClassInit", "()V", (void*) class_init },
+    { "nativeInitialize", "()V", (void*) initialize },
+    { "nativeRelease", "()V", (void*) release },
+    { "nativeIsSupported", "()Z", (void*) is_supported },
+    { "nativeGetSupportedActivities", "()[Ljava/lang/String;", (void*) get_supported_activities },
+    { "nativeEnableActivityEvent", "(IIJ)I", (void*) enable_activity_event },
+    { "nativeDisableActivityEvent", "(II)I", (void*) disable_activity_event },
+    { "nativeFlush", "()I", (void*) flush },
+};
+
+/**
+ * Registration method invoked in JNI load.
+ */
+int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env) {
+    return jniRegisterNativeMethods(
+            env,
+            "android/hardware/location/ActivityRecognitionHardware",
+            sMethods,
+            NELEM(sMethods));
+}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 7d63ec9..7837248 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -45,6 +45,7 @@
 #include <meminfo/sysmeminfo.h>
 #include <memtrack/memtrack.h>
 #include <memunreachable/memunreachable.h>
+#include <android-base/strings.h>
 #include "android_os_Debug.h"
 
 namespace android
@@ -231,244 +232,162 @@
     return err;
 }
 
-static void read_mapinfo(FILE *fp, stats_t* stats, bool* foundSwapPss)
-{
-    char line[1024];
-    int len, nameLen;
-    bool skip, done = false;
-
-    unsigned pss = 0, swappable_pss = 0, rss = 0;
-    float sharing_proportion = 0.0;
-    unsigned shared_clean = 0, shared_dirty = 0;
-    unsigned private_clean = 0, private_dirty = 0;
-    unsigned swapped_out = 0, swapped_out_pss = 0;
-    bool is_swappable = false;
-    unsigned temp;
-
-    uint64_t start;
-    uint64_t end = 0;
-    uint64_t prevEnd = 0;
-    char* name;
-    int name_pos;
-
-    int whichHeap = HEAP_UNKNOWN;
-    int subHeap = HEAP_UNKNOWN;
-    int prevHeap = HEAP_UNKNOWN;
-
-    *foundSwapPss = false;
-
-    if(fgets(line, sizeof(line), fp) == 0) return;
-
-    while (!done) {
-        prevHeap = whichHeap;
-        prevEnd = end;
-        whichHeap = HEAP_UNKNOWN;
-        subHeap = HEAP_UNKNOWN;
-        skip = false;
-        is_swappable = false;
-
-        len = strlen(line);
-        if (len < 1) return;
-        line[--len] = 0;
-
-        if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
-            skip = true;
-        } else {
-            while (isspace(line[name_pos])) {
-                name_pos += 1;
-            }
-            name = line + name_pos;
-            nameLen = strlen(name);
-            // Trim the end of the line if it is " (deleted)".
-            const char* deleted_str = " (deleted)";
-            if (nameLen > (int)strlen(deleted_str) &&
-                strcmp(name+nameLen-strlen(deleted_str), deleted_str) == 0) {
-                nameLen -= strlen(deleted_str);
-                name[nameLen] = '\0';
-            }
-            if ((strstr(name, "[heap]") == name)) {
-                whichHeap = HEAP_NATIVE;
-            } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
-                whichHeap = HEAP_NATIVE;
-            } else if (strncmp(name, "[stack", 6) == 0) {
-                whichHeap = HEAP_STACK;
-            } else if (nameLen > 3 && strcmp(name+nameLen-3, ".so") == 0) {
-                whichHeap = HEAP_SO;
-                is_swappable = true;
-            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".jar") == 0) {
-                whichHeap = HEAP_JAR;
-                is_swappable = true;
-            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".apk") == 0) {
-                whichHeap = HEAP_APK;
-                is_swappable = true;
-            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".ttf") == 0) {
-                whichHeap = HEAP_TTF;
-                is_swappable = true;
-            } else if ((nameLen > 4 && strstr(name, ".dex") != NULL) ||
-                       (nameLen > 5 && strcmp(name+nameLen-5, ".odex") == 0)) {
-                whichHeap = HEAP_DEX;
-                subHeap = HEAP_DEX_APP_DEX;
-                is_swappable = true;
-            } else if (nameLen > 5 && strcmp(name+nameLen-5, ".vdex") == 0) {
-                whichHeap = HEAP_DEX;
-                // Handle system@framework@boot* and system/framework/boot*
-                if (strstr(name, "@boot") != NULL || strstr(name, "/boot") != NULL) {
-                    subHeap = HEAP_DEX_BOOT_VDEX;
-                } else {
-                    subHeap = HEAP_DEX_APP_VDEX;
-                }
-                is_swappable = true;
-            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".oat") == 0) {
-                whichHeap = HEAP_OAT;
-                is_swappable = true;
-            } else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
-                whichHeap = HEAP_ART;
-                // Handle system@framework@boot* and system/framework/boot*
-                if (strstr(name, "@boot") != NULL || strstr(name, "/boot") != NULL) {
-                    subHeap = HEAP_ART_BOOT;
-                } else {
-                    subHeap = HEAP_ART_APP;
-                }
-                is_swappable = true;
-            } else if (strncmp(name, "/dev/", 5) == 0) {
-                whichHeap = HEAP_UNKNOWN_DEV;
-                if (strncmp(name, "/dev/kgsl-3d0", 13) == 0) {
-                    whichHeap = HEAP_GL_DEV;
-                } else if (strncmp(name, "/dev/ashmem/CursorWindow", 24) == 0) {
-                    whichHeap = HEAP_CURSOR;
-                } else if (strncmp(name, "/dev/ashmem", 11)) {
-                    whichHeap = HEAP_ASHMEM;
-                }
-            } else if (strncmp(name, "[anon:", 6) == 0) {
-                whichHeap = HEAP_UNKNOWN;
-                if (strncmp(name, "[anon:dalvik-", 13) == 0) {
-                    whichHeap = HEAP_DALVIK_OTHER;
-                    if (strstr(name, "[anon:dalvik-LinearAlloc") == name) {
-                        subHeap = HEAP_DALVIK_OTHER_LINEARALLOC;
-                    } else if ((strstr(name, "[anon:dalvik-alloc space") == name) ||
-                               (strstr(name, "[anon:dalvik-main space") == name)) {
-                        // This is the regular Dalvik heap.
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_NORMAL;
-                    } else if (strstr(name, "[anon:dalvik-large object space") == name ||
-                               strstr(name, "[anon:dalvik-free list large object space")
-                                   == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_LARGE;
-                    } else if (strstr(name, "[anon:dalvik-non moving space") == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_NON_MOVING;
-                    } else if (strstr(name, "[anon:dalvik-zygote space") == name) {
-                        whichHeap = HEAP_DALVIK;
-                        subHeap = HEAP_DALVIK_ZYGOTE;
-                    } else if (strstr(name, "[anon:dalvik-indirect ref") == name) {
-                        subHeap = HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
-                    } else if (strstr(name, "[anon:dalvik-jit-code-cache") == name ||
-                               strstr(name, "[anon:dalvik-data-code-cache") == name) {
-                        subHeap = HEAP_DALVIK_OTHER_CODE_CACHE;
-                    } else if (strstr(name, "[anon:dalvik-CompilerMetadata") == name) {
-                        subHeap = HEAP_DALVIK_OTHER_COMPILER_METADATA;
-                    } else {
-                        subHeap = HEAP_DALVIK_OTHER_ACCOUNTING;  // Default to accounting.
-                    }
-                }
-            } else if (nameLen > 0) {
-                whichHeap = HEAP_UNKNOWN_MAP;
-            } else if (start == prevEnd && prevHeap == HEAP_SO) {
-                // bss section of a shared library.
-                whichHeap = HEAP_SO;
-            }
-        }
-
-        //ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
-        //    isSqliteHeap, line);
-
-        shared_clean = 0;
-        shared_dirty = 0;
-        private_clean = 0;
-        private_dirty = 0;
-        swapped_out = 0;
-        swapped_out_pss = 0;
-
-        while (true) {
-            if (fgets(line, 1024, fp) == 0) {
-                done = true;
-                break;
-            }
-
-            if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
-                /* size = temp; */
-            } else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
-                rss = temp;
-            } else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
-                pss = temp;
-            } else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
-                shared_clean = temp;
-            } else if (line[0] == 'S' && sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
-                shared_dirty = temp;
-            } else if (line[0] == 'P' && sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
-                private_clean = temp;
-            } else if (line[0] == 'P' && sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
-                private_dirty = temp;
-            } else if (line[0] == 'R' && sscanf(line, "Referenced: %d kB", &temp) == 1) {
-                /* referenced = temp; */
-            } else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
-                swapped_out = temp;
-            } else if (line[0] == 'S' && sscanf(line, "SwapPss: %d kB", &temp) == 1) {
-                *foundSwapPss = true;
-                swapped_out_pss = temp;
-            } else if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
-                // looks like a new mapping
-                // example: "10000000-10001000 ---p 10000000 00:00 0"
-                break;
-            }
-        }
-
-        if (!skip) {
-            if (is_swappable && (pss > 0)) {
-                sharing_proportion = 0.0;
-                if ((shared_clean > 0) || (shared_dirty > 0)) {
-                    sharing_proportion = (pss - private_clean
-                            - private_dirty)/(shared_clean+shared_dirty);
-                }
-                swappable_pss = (sharing_proportion*shared_clean) + private_clean;
-            } else
-                swappable_pss = 0;
-
-            stats[whichHeap].pss += pss;
-            stats[whichHeap].swappablePss += swappable_pss;
-            stats[whichHeap].rss += rss;
-            stats[whichHeap].privateDirty += private_dirty;
-            stats[whichHeap].sharedDirty += shared_dirty;
-            stats[whichHeap].privateClean += private_clean;
-            stats[whichHeap].sharedClean += shared_clean;
-            stats[whichHeap].swappedOut += swapped_out;
-            stats[whichHeap].swappedOutPss += swapped_out_pss;
-            if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER ||
-                    whichHeap == HEAP_DEX || whichHeap == HEAP_ART) {
-                stats[subHeap].pss += pss;
-                stats[subHeap].swappablePss += swappable_pss;
-                stats[subHeap].rss += rss;
-                stats[subHeap].privateDirty += private_dirty;
-                stats[subHeap].sharedDirty += shared_dirty;
-                stats[subHeap].privateClean += private_clean;
-                stats[subHeap].sharedClean += shared_clean;
-                stats[subHeap].swappedOut += swapped_out;
-                stats[subHeap].swappedOutPss += swapped_out_pss;
-            }
-        }
-    }
-}
-
 static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
 {
     *foundSwapPss = false;
+    uint64_t prev_end = 0;
+    int prev_heap = HEAP_UNKNOWN;
 
     std::string smaps_path = base::StringPrintf("/proc/%d/smaps", pid);
-    UniqueFile fp = MakeUniqueFile(smaps_path.c_str(), "re");
-    if (fp == nullptr) return;
+    auto vma_scan = [&](const meminfo::Vma& vma) {
+        int which_heap = HEAP_UNKNOWN;
+        int sub_heap = HEAP_UNKNOWN;
+        bool is_swappable = false;
+        std::string name;
+        if (base::EndsWith(vma.name, " (deleted)")) {
+            name = vma.name.substr(0, vma.name.size() - strlen(" (deleted)"));
+        } else {
+            name = vma.name;
+        }
 
-    read_mapinfo(fp.get(), stats, foundSwapPss);
+        uint32_t namesz = name.size();
+        if (base::StartsWith(name, "[heap]")) {
+            which_heap = HEAP_NATIVE;
+        } else if (base::StartsWith(name, "[anon:libc_malloc]")) {
+            which_heap = HEAP_NATIVE;
+        } else if (base::StartsWith(name, "[stack")) {
+            which_heap = HEAP_NATIVE;
+        } else if (base::EndsWith(name, ".so")) {
+            which_heap = HEAP_SO;
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".jar")) {
+            which_heap = HEAP_JAR;
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".apk")) {
+            which_heap = HEAP_APK;
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".ttf")) {
+            which_heap = HEAP_TTF;
+            is_swappable = true;
+        } else if ((base::EndsWith(name, ".odex")) ||
+                (namesz > 4 && strstr(name.c_str(), ".dex") != nullptr)) {
+            which_heap = HEAP_DEX;
+            sub_heap = HEAP_DEX_APP_DEX;
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".vdex")) {
+            which_heap = HEAP_DEX;
+            // Handle system@framework@boot and system/framework/boot
+            if ((strstr(name.c_str(), "@boot") != nullptr) ||
+                    (strstr(name.c_str(), "/boot"))) {
+                sub_heap = HEAP_DEX_BOOT_VDEX;
+            } else {
+                sub_heap = HEAP_DEX_APP_VDEX;
+            }
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".oat")) {
+            which_heap = HEAP_OAT;
+            is_swappable = true;
+        } else if (base::EndsWith(name, ".art")) {
+            which_heap = HEAP_ART;
+            // Handle system@framework@boot* and system/framework/boot*
+            if ((strstr(name.c_str(), "@boot") != nullptr) ||
+                    (strstr(name.c_str(), "/boot"))) {
+                sub_heap = HEAP_DEX_BOOT_VDEX;
+            } else {
+                sub_heap = HEAP_DEX_APP_VDEX;
+            }
+            is_swappable = true;
+        } else if (base::StartsWith(name, "/dev/")) {
+            which_heap = HEAP_UNKNOWN_DEV;
+            if (base::StartsWith(name, "/dev/kgsl-3d0")) {
+                which_heap = HEAP_GL_DEV;
+            } else if (base::StartsWith(name, "/dev/ashmem/CursorWindow")) {
+                which_heap = HEAP_CURSOR;
+            } else if (base::StartsWith(name, "/dev/ashmem")) {
+                which_heap = HEAP_ASHMEM;
+            }
+        } else if (base::StartsWith(name, "[anon:")) {
+            which_heap = HEAP_UNKNOWN;
+            if (base::StartsWith(name, "[anon:dalvik-")) {
+                which_heap = HEAP_DALVIK_OTHER;
+                if (base::StartsWith(name, "[anon:dalvik-LinearAlloc")) {
+                    sub_heap = HEAP_DALVIK_OTHER_LINEARALLOC;
+                } else if (base::StartsWith(name, "[anon:dalvik-alloc space") ||
+                        base::StartsWith(name, "[anon:dalvik-main space")) {
+                    // This is the regular Dalvik heap.
+                    which_heap = HEAP_DALVIK;
+                    sub_heap = HEAP_DALVIK_NORMAL;
+                } else if (base::StartsWith(name,
+                            "[anon:dalvik-large object space") ||
+                        base::StartsWith(
+                            name, "[anon:dalvik-free list large object space")) {
+                    which_heap = HEAP_DALVIK;
+                    sub_heap = HEAP_DALVIK_LARGE;
+                } else if (base::StartsWith(name, "[anon:dalvik-non moving space")) {
+                    which_heap = HEAP_DALVIK;
+                    sub_heap = HEAP_DALVIK_NON_MOVING;
+                } else if (base::StartsWith(name, "[anon:dalvik-zygote space")) {
+                    which_heap = HEAP_DALVIK;
+                    sub_heap = HEAP_DALVIK_ZYGOTE;
+                } else if (base::StartsWith(name, "[anon:dalvik-indirect ref")) {
+                    sub_heap = HEAP_DALVIK_OTHER_INDIRECT_REFERENCE_TABLE;
+                } else if (base::StartsWith(name, "[anon:dalvik-jit-code-cache") ||
+                        base::StartsWith(name, "[anon:dalvik-data-code-cache")) {
+                    sub_heap = HEAP_DALVIK_OTHER_CODE_CACHE;
+                } else if (base::StartsWith(name, "[anon:dalvik-CompilerMetadata")) {
+                    sub_heap = HEAP_DALVIK_OTHER_COMPILER_METADATA;
+                } else {
+                    sub_heap = HEAP_DALVIK_OTHER_ACCOUNTING;  // Default to accounting.
+                }
+            }
+        } else if (namesz > 0) {
+            which_heap = HEAP_UNKNOWN_MAP;
+        } else if (vma.start == prev_end && prev_heap == HEAP_SO) {
+            // bss section of a shared library
+            which_heap = HEAP_SO;
+        }
+
+        prev_end = vma.end;
+        prev_heap = which_heap;
+
+        const meminfo::MemUsage& usage = vma.usage;
+        if (usage.swap_pss > 0 && *foundSwapPss != true) {
+            *foundSwapPss = true;
+        }
+
+        uint64_t swapable_pss = 0;
+        if (is_swappable && (usage.pss > 0)) {
+            float sharing_proportion = 0.0;
+            if ((usage.shared_clean > 0) || (usage.shared_dirty > 0)) {
+                sharing_proportion = (usage.pss - usage.uss) / (usage.shared_clean + usage.shared_dirty);
+            }
+            swapable_pss = (sharing_proportion * usage.shared_clean) + usage.private_clean;
+        }
+
+        stats[which_heap].pss += usage.pss;
+        stats[which_heap].swappablePss += swapable_pss;
+        stats[which_heap].rss += usage.rss;
+        stats[which_heap].privateDirty += usage.private_dirty;
+        stats[which_heap].sharedDirty += usage.shared_dirty;
+        stats[which_heap].privateClean += usage.private_clean;
+        stats[which_heap].sharedClean += usage.shared_clean;
+        stats[which_heap].swappedOut += usage.swap;
+        stats[which_heap].swappedOutPss += usage.swap_pss;
+        if (which_heap == HEAP_DALVIK || which_heap == HEAP_DALVIK_OTHER ||
+                which_heap == HEAP_DEX || which_heap == HEAP_ART) {
+            stats[sub_heap].pss += usage.pss;
+            stats[sub_heap].swappablePss += swapable_pss;
+            stats[sub_heap].rss += usage.rss;
+            stats[sub_heap].privateDirty += usage.private_dirty;
+            stats[sub_heap].sharedDirty += usage.shared_dirty;
+            stats[sub_heap].privateClean += usage.private_clean;
+            stats[sub_heap].sharedClean += usage.shared_clean;
+            stats[sub_heap].swappedOut += usage.swap;
+            stats[sub_heap].swappedOutPss += usage.swap_pss;
+        }
+    };
+
+    meminfo::ForEachVmaFromFile(smaps_path, vma_scan);
 }
 
 static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index d60d1a6..3661ff2 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -38,6 +38,8 @@
   "/dev/null",
   "/dev/socket/zygote",
   "/dev/socket/zygote_secondary",
+  "/dev/socket/blastula_pool",
+  "/dev/socket/blastula_pool_secondary",
   "/dev/socket/webview_zygote",
   "/dev/socket/heapprofd",
   "/sys/kernel/debug/tracing/trace_marker",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5995640..44b2c31 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -705,6 +705,9 @@
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">false</bool>
 
+    <!-- Flag indicating whether we should enable the adaptive sleep.-->
+    <bool name="config_adaptive_sleep_available">false</bool>
+
     <!-- Flag indicating whether we should enable smart battery. -->
     <bool name="config_smart_battery_available">false</bool>
 
@@ -931,6 +934,10 @@
          in hardware. -->
     <bool name="config_setColorTransformAccelerated">false</bool>
 
+    <!-- Boolean indicating whether the HWC setColorTransform function can be performed efficiently
+         in hardware for individual layers. -->
+    <bool name="config_setColorTransformAcceleratedPerLayer">false</bool>
+
     <!-- Control whether Night display is available. This should only be enabled on devices
          that have a HWC implementation that can apply the matrix passed to setColorTransform
          without impacting power, performance, and app compatibility (e.g. protected content). -->
@@ -1743,6 +1750,19 @@
          config_enableGeofenceOverlay is false. -->
     <string name="config_geofenceProviderPackageName" translatable="false">@null</string>
 
+    <!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware
+         Activity-Recognition to be replaced by an app at run-time. When disabled, only the
+         config_activityRecognitionHardwarePackageName package will be searched for
+         its implementation, otherwise packages whose signature matches the
+         signatures of config_locationProviderPackageNames will be searched, and
+         the service with the highest version number will be picked. Anyone who
+         wants to disable the overlay mechanism can set it to false.
+         -->
+    <bool name="config_enableActivityRecognitionHardwareOverlay" translatable="false">true</bool>
+    <!-- Package name providing Hardware Activity-Recognition API support. Used only when
+         config_enableActivityRecognitionHardwareOverlay is false. -->
+    <string name="config_activityRecognitionHardwarePackageName" translatable="false">@null</string>
+
     <!-- Package name(s) containing location provider support.
          These packages can contain services implementing location providers,
          such as the Geocode Provider, Network Location Provider, and
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0878562..f2b4b9c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3353,9 +3353,9 @@
     <string name="wifi_available_action_all_networks">All networks</string>
 
     <!-- Notification title for a connection to a app suggested wireless network.-->
-    <string name="wifi_suggestion_title">Connected to Wi\u2011Fi network proposed by <xliff:g id="name" example="App123">%s</xliff:g></string>
+    <string name="wifi_suggestion_title">A Wi\u2011Fi network proposed by <xliff:g id="name" example="App123">%s</xliff:g> is available</string>
     <!-- Notification content for a connection to a app suggested wireless network.-->
-    <string name="wifi_suggestion_content">Do you want to let <xliff:g id="name" example="App123">%s</xliff:g> propose networks for you?</string>
+    <string name="wifi_suggestion_content">Do you want to connect to networks proposed by <xliff:g id="name" example="App123">%s</xliff:g>?</string>
     <!-- Notification action for allowing app specified in the notification body.-->
     <string name="wifi_suggestion_action_allow_app">Yes</string>
     <!-- Notification action for disallowing app specified in the notification body.-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 53c33a3..11fc66a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1845,6 +1845,7 @@
   <java-symbol type="array" name="config_defaultNotificationVibePattern" />
   <java-symbol type="array" name="config_notificationFallbackVibePattern" />
   <java-symbol type="bool" name="config_useAttentionLight" />
+  <java-symbol type="bool" name="config_adaptive_sleep_available" />
   <java-symbol type="bool" name="config_animateScreenLights" />
   <java-symbol type="bool" name="config_automatic_brightness_available" />
   <java-symbol type="bool" name="config_smart_battery_available" />
@@ -1853,6 +1854,7 @@
   <java-symbol type="bool" name="config_enableNightMode" />
   <java-symbol type="bool" name="config_tintNotificationActionButtons" />
   <java-symbol type="bool" name="config_dozeAfterScreenOffByDefault" />
+  <java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
   <java-symbol type="bool" name="config_enableFusedLocationOverlay" />
   <java-symbol type="bool" name="config_enableHardwareFlpOverlay" />
   <java-symbol type="bool" name="config_enableGeocoderOverlay" />
@@ -2021,6 +2023,7 @@
   <java-symbol type="string" name="car_mode_disable_notification_title" />
   <java-symbol type="string" name="chooser_wallpaper" />
   <java-symbol type="string" name="config_datause_iface" />
+  <java-symbol type="string" name="config_activityRecognitionHardwarePackageName" />
   <java-symbol type="string" name="config_fusedLocationProviderPackageName" />
   <java-symbol type="string" name="config_hardwareFlpPackageName" />
   <java-symbol type="string" name="config_geocoderProviderPackageName" />
@@ -3031,6 +3034,7 @@
   <java-symbol type="drawable" name="ic_doc_generic" />
 
   <java-symbol type="bool" name="config_setColorTransformAccelerated" />
+  <java-symbol type="bool" name="config_setColorTransformAcceleratedPerLayer" />
   <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
   <java-symbol type="bool" name="config_nightDisplayAvailable" />
   <java-symbol type="bool" name="config_allowDisablingAssistDisclosure" />
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 0179ead..9cac7e7 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -43,6 +43,10 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.Before;
@@ -76,13 +80,13 @@
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsCpuTimesTest {
     @Mock
-    KernelUidCpuTimeReader mKernelUidCpuTimeReader;
+    KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
     @Mock
-    KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
+    KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
     @Mock
-    KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader;
+    KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
     @Mock
-    KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader;
+    KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
     @Mock
     BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
     @Mock
@@ -98,10 +102,10 @@
 
         mClocks = new MockClocks();
         mBatteryStatsImpl = new MockBatteryStatsImpl(mClocks)
-                .setKernelUidCpuTimeReader(mKernelUidCpuTimeReader)
-                .setKernelUidCpuFreqTimeReader(mKernelUidCpuFreqTimeReader)
-                .setKernelUidCpuActiveTimeReader(mKernelUidCpuActiveTimeReader)
-                .setKernelUidCpuClusterTimeReader(mKernelUidCpuClusterTimeReader)
+                .setKernelCpuUidUserSysTimeReader(mCpuUidUserSysTimeReader)
+                .setKernelCpuUidFreqTimeReader(mCpuUidFreqTimeReader)
+                .setKernelCpuUidActiveTimeReader(mCpuUidActiveTimeReader)
+                .setKernelCpuUidClusterTimeReader(mCpuUidClusterTimeReader)
                 .setUserInfoProvider(mUserInfoProvider);
     }
 
@@ -113,21 +117,21 @@
         final int numClusters = 3;
         initKernelCpuSpeedReaders(numClusters);
         final long[] freqs = {1, 12, 123, 12, 1234};
-        when(mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs);
+        when(mCpuUidFreqTimeReader.readFreqs(mPowerProfile)).thenReturn(freqs);
 
         // RUN
         mBatteryStatsImpl.updateCpuTimeLocked(false, false);
 
         // VERIFY
         assertArrayEquals("Unexpected cpu freqs", freqs, mBatteryStatsImpl.getCpuFreqs());
-        verify(mKernelUidCpuTimeReader).readDelta(null);
-        verify(mKernelUidCpuFreqTimeReader).readDelta(null);
+        verify(mCpuUidUserSysTimeReader).readDelta(null);
+        verify(mCpuUidFreqTimeReader).readDelta(null);
         for (int i = 0; i < numClusters; ++i) {
             verify(mKernelCpuSpeedReaders[i]).readDelta();
         }
 
         // Prepare for next test
-        Mockito.reset(mUserInfoProvider, mKernelUidCpuFreqTimeReader, mKernelUidCpuTimeReader);
+        Mockito.reset(mUserInfoProvider, mCpuUidFreqTimeReader, mCpuUidUserSysTimeReader);
         for (int i = 0; i < numClusters; ++i) {
             Mockito.reset(mKernelCpuSpeedReaders[i]);
         }
@@ -140,17 +144,18 @@
 
         // VERIFY
         verify(mUserInfoProvider).refreshUserIds();
-        verify(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        verify(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
         // perClusterTimesAvailable is called twice, once in updateCpuTimeLocked() and the other
         // in readKernelUidCpuFreqTimesLocked.
-        verify(mKernelUidCpuFreqTimeReader, times(2)).perClusterTimesAvailable();
-        verify(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
-        verify(mKernelUidCpuActiveTimeReader).readDelta(
-                any(KernelUidCpuActiveTimeReader.Callback.class));
-        verify(mKernelUidCpuClusterTimeReader).readDelta(
-                any(KernelUidCpuClusterTimeReader.Callback.class));
-        verifyNoMoreInteractions(mKernelUidCpuFreqTimeReader);
+        verify(mCpuUidFreqTimeReader, times(2)).perClusterTimesAvailable();
+        verify(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
+        verify(mCpuUidActiveTimeReader).readDelta(
+                any(KernelCpuUidActiveTimeReader.Callback.class));
+        verify(mCpuUidClusterTimeReader).readDelta(
+                any(KernelCpuUidClusterTimeReader.Callback.class));
+        verifyNoMoreInteractions(mCpuUidFreqTimeReader);
         for (int i = 0; i < numClusters; ++i) {
             verify(mKernelCpuSpeedReaders[i]).readDelta();
         }
@@ -253,13 +258,14 @@
                 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
+                callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
             }
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         final SparseLongArray updatedUids = new SparseLongArray();
@@ -287,13 +293,14 @@
                 {9379, 3332409833484l}, {493247, 723234}, {3247819, 123348}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], deltasUs[i][0], deltasUs[i][1]);
+                callback.onUidCpuTime(testUids[i], deltasUs[i]);
             }
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
@@ -326,13 +333,14 @@
                 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
+                callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
             }
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
@@ -350,7 +358,7 @@
             assertEquals("Unexpected system cpu time for uid=" + testUids[i],
                     uidTimesUs[i][1], u.getSystemCpuTimeUs(STATS_SINCE_CHARGED));
         }
-        verify(mKernelUidCpuTimeReader).removeUid(isolatedUid);
+        verify(mCpuUidUserSysTimeReader).removeUid(isolatedUid);
 
         // Add an isolated uid mapping and repeat the test.
 
@@ -361,13 +369,14 @@
                 {9379, 3332409833484l}, {493247, 723234}, {3247819, 123348}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], deltasUs[i][0], deltasUs[i][1]);
+                callback.onUidCpuTime(testUids[i], deltasUs[i]);
             }
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
@@ -414,15 +423,16 @@
                 {12, 34}, {34897394, 3123983}, {79775429834l, 8430434903489l}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
+                callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuTime(invalidUid, 3879, 239);
+            callback.onUidCpuTime(invalidUid, new long[]{3879, 239});
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuTimesLocked(null, null, true);
@@ -438,7 +448,7 @@
         }
         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
                 mBatteryStatsImpl.getUidStats().get(invalidUid));
-        verify(mKernelUidCpuTimeReader).removeUid(invalidUid);
+        verify(mCpuUidUserSysTimeReader).removeUid(invalidUid);
     }
 
     @Test
@@ -462,13 +472,14 @@
                 {12, 34}, {3394, 3123}, {7977, 80434}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuTimeReader.Callback callback =
-                    (KernelUidCpuTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidUserSysTimeReader.Callback<long[]> callback =
+                    (KernelCpuUidUserSysTimeReader.Callback<long[]>) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuTime(testUids[i], uidTimesUs[i][0], uidTimesUs[i][1]);
+                callback.onUidCpuTime(testUids[i], uidTimesUs[i]);
             }
             return null;
-        }).when(mKernelUidCpuTimeReader).readDelta(any(KernelUidCpuTimeReader.Callback.class));
+        }).when(mCpuUidUserSysTimeReader).readDelta(
+                any(KernelCpuUidUserSysTimeReader.Callback.class));
 
         // RUN
         final SparseLongArray updatedUids = new SparseLongArray();
@@ -541,14 +552,14 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -574,14 +585,14 @@
                 {43, 3345, 2143, 123, 4554}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
@@ -624,15 +635,15 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
-        when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
+        when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -668,14 +679,14 @@
                 {43, 3345, 2143, 123, 4554}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
@@ -734,15 +745,15 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
-        when(mKernelUidCpuFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
+        when(mCpuUidFreqTimeReader.perClusterTimesAvailable()).thenReturn(true);
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(partialTimers, true, false);
@@ -824,14 +835,14 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -857,14 +868,14 @@
                 {43, 3345, 2143, 123, 4554, 9374983794839l, 979875}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, true);
@@ -901,14 +912,14 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -927,7 +938,7 @@
             assertNull("Unexpected screen-off cpu times for uid=" + testUids[i],
                     u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED));
         }
-        verify(mKernelUidCpuFreqTimeReader).removeUid(isolatedUid);
+        verify(mCpuUidFreqTimeReader).removeUid(isolatedUid);
 
 
         // Add an isolated uid mapping and repeat the test.
@@ -941,14 +952,14 @@
                 {43, 3345, 2143, 123, 4554}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -996,16 +1007,16 @@
                 {8, 25, 3, 0, 42}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuFreqTimeReader.Callback callback =
-                    (KernelUidCpuFreqTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidFreqTimeReader.Callback callback =
+                    (KernelCpuUidFreqTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuFreqTime(invalidUid, new long[]{12, 839, 32, 34, 21});
+            callback.onUidCpuTime(invalidUid, new long[]{12, 839, 32, 34, 21});
             return null;
-        }).when(mKernelUidCpuFreqTimeReader).readDelta(
-                any(KernelUidCpuFreqTimeReader.Callback.class));
+        }).when(mCpuUidFreqTimeReader).readDelta(
+                any(KernelCpuUidFreqTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuFreqTimesLocked(null, true, false);
@@ -1022,7 +1033,7 @@
         }
         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
                 mBatteryStatsImpl.getUidStats().get(invalidUid));
-        verify(mKernelUidCpuFreqTimeReader).removeUid(invalidUid);
+        verify(mCpuUidFreqTimeReader).removeUid(invalidUid);
     }
 
     @Test
@@ -1039,14 +1050,14 @@
         });
         final long[] uidTimesMs = {8000, 25000, 3000, 0, 42000};
         doAnswer(invocation -> {
-            final KernelUidCpuActiveTimeReader.Callback callback =
-                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidActiveTimeReader.Callback callback =
+                    (KernelCpuUidActiveTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuActiveTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuActiveTimeReader).readDelta(
-                any(KernelUidCpuActiveTimeReader.Callback.class));
+        }).when(mCpuUidActiveTimeReader).readDelta(
+                any(KernelCpuUidActiveTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
@@ -1065,14 +1076,14 @@
         updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
         final long[] deltasMs = {43000, 3345000, 2143000, 123000, 4554000};
         doAnswer(invocation -> {
-            final KernelUidCpuActiveTimeReader.Callback callback =
-                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidActiveTimeReader.Callback callback =
+                    (KernelCpuUidActiveTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuActiveTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuActiveTimeReader).readDelta(
-                any(KernelUidCpuActiveTimeReader.Callback.class));
+        }).when(mCpuUidActiveTimeReader).readDelta(
+                any(KernelCpuUidActiveTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
@@ -1103,16 +1114,16 @@
         });
         final long[] uidTimesMs = {8000, 25000, 3000, 0, 42000};
         doAnswer(invocation -> {
-            final KernelUidCpuActiveTimeReader.Callback callback =
-                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidActiveTimeReader.Callback callback =
+                    (KernelCpuUidActiveTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuActiveTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuActiveTime(invalidUid, 1200L);
+            callback.onUidCpuTime(invalidUid, 1200L);
             return null;
-        }).when(mKernelUidCpuActiveTimeReader).readDelta(
-                any(KernelUidCpuActiveTimeReader.Callback.class));
+        }).when(mCpuUidActiveTimeReader).readDelta(
+                any(KernelCpuUidActiveTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked(true);
@@ -1126,7 +1137,7 @@
         }
         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
                 mBatteryStatsImpl.getUidStats().get(invalidUid));
-        verify(mKernelUidCpuActiveTimeReader).removeUid(invalidUid);
+        verify(mCpuUidActiveTimeReader).removeUid(invalidUid);
     }
 
     @Test
@@ -1147,14 +1158,14 @@
                 {8000, 0}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuClusterTimeReader.Callback callback =
-                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidClusterTimeReader.Callback callback =
+                    (KernelCpuUidClusterTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuPolicyTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuClusterTimeReader).readDelta(
-                any(KernelUidCpuClusterTimeReader.Callback.class));
+        }).when(mCpuUidClusterTimeReader).readDelta(
+                any(KernelCpuUidClusterTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
@@ -1177,14 +1188,14 @@
                 {43000, 3345000}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuClusterTimeReader.Callback callback =
-                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidClusterTimeReader.Callback callback =
+                    (KernelCpuUidClusterTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuPolicyTime(testUids[i], deltasMs[i]);
+                callback.onUidCpuTime(testUids[i], deltasMs[i]);
             }
             return null;
-        }).when(mKernelUidCpuClusterTimeReader).readDelta(
-                any(KernelUidCpuClusterTimeReader.Callback.class));
+        }).when(mCpuUidClusterTimeReader).readDelta(
+                any(KernelCpuUidClusterTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
@@ -1193,7 +1204,8 @@
         for (int i = 0; i < testUids.length; ++i) {
             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
             assertNotNull("No entry for uid=" + testUids[i], u);
-            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], sum(uidTimesMs[i], deltasMs[i]),
+            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i],
+                    sum(uidTimesMs[i], deltasMs[i]),
                     u.getCpuClusterTimes());
         }
     }
@@ -1219,16 +1231,16 @@
                 {8000, 0}
         };
         doAnswer(invocation -> {
-            final KernelUidCpuClusterTimeReader.Callback callback =
-                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            final KernelCpuUidClusterTimeReader.Callback callback =
+                    (KernelCpuUidClusterTimeReader.Callback) invocation.getArguments()[0];
             for (int i = 0; i < testUids.length; ++i) {
-                callback.onUidCpuPolicyTime(testUids[i], uidTimesMs[i]);
+                callback.onUidCpuTime(testUids[i], uidTimesMs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuPolicyTime(invalidUid, new long[] {400, 1000});
+            callback.onUidCpuTime(invalidUid, new long[]{400, 1000});
             return null;
-        }).when(mKernelUidCpuClusterTimeReader).readDelta(
-                any(KernelUidCpuClusterTimeReader.Callback.class));
+        }).when(mCpuUidClusterTimeReader).readDelta(
+                any(KernelCpuUidClusterTimeReader.Callback.class));
 
         // RUN
         mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked(true);
@@ -1242,7 +1254,7 @@
         }
         assertNull("There shouldn't be an entry for invalid uid=" + invalidUid,
                 mBatteryStatsImpl.getUidStats().get(invalidUid));
-        verify(mKernelUidCpuClusterTimeReader).removeUid(invalidUid);
+        verify(mCpuUidClusterTimeReader).removeUid(invalidUid);
     }
 
     @Test
@@ -1268,25 +1280,25 @@
         mClocks.realtime = mClocks.uptime = 400_000;
         mBatteryStatsImpl.clearPendingRemovedUids();
         assertEquals(1, mBatteryStatsImpl.getPendingRemovedUids().size());
-        verify(mKernelUidCpuActiveTimeReader).removeUid(1);
-        verify(mKernelUidCpuActiveTimeReader).removeUidsInRange(5, 10);
-        verify(mKernelUidCpuClusterTimeReader).removeUid(1);
-        verify(mKernelUidCpuClusterTimeReader).removeUidsInRange(5, 10);
-        verify(mKernelUidCpuFreqTimeReader).removeUid(1);
-        verify(mKernelUidCpuFreqTimeReader).removeUidsInRange(5, 10);
-        verify(mKernelUidCpuTimeReader).removeUid(1);
-        verify(mKernelUidCpuTimeReader).removeUidsInRange(5, 10);
+        verify(mCpuUidActiveTimeReader).removeUid(1);
+        verify(mCpuUidActiveTimeReader).removeUidsInRange(5, 10);
+        verify(mCpuUidClusterTimeReader).removeUid(1);
+        verify(mCpuUidClusterTimeReader).removeUidsInRange(5, 10);
+        verify(mCpuUidFreqTimeReader).removeUid(1);
+        verify(mCpuUidFreqTimeReader).removeUidsInRange(5, 10);
+        verify(mCpuUidUserSysTimeReader).removeUid(1);
+        verify(mCpuUidUserSysTimeReader).removeUidsInRange(5, 10);
 
         mClocks.realtime = mClocks.uptime = 800_000;
         mBatteryStatsImpl.clearPendingRemovedUids();
         assertEquals(0, mBatteryStatsImpl.getPendingRemovedUids().size());
-        verify(mKernelUidCpuActiveTimeReader).removeUid(100);
-        verify(mKernelUidCpuClusterTimeReader).removeUid(100);
-        verify(mKernelUidCpuFreqTimeReader).removeUid(100);
-        verify(mKernelUidCpuTimeReader).removeUid(100);
+        verify(mCpuUidActiveTimeReader).removeUid(100);
+        verify(mCpuUidClusterTimeReader).removeUid(100);
+        verify(mCpuUidFreqTimeReader).removeUid(100);
+        verify(mCpuUidUserSysTimeReader).removeUid(100);
 
-        verifyNoMoreInteractions(mKernelUidCpuActiveTimeReader, mKernelUidCpuClusterTimeReader,
-                mKernelUidCpuFreqTimeReader, mKernelUidCpuTimeReader);
+        verifyNoMoreInteractions(mCpuUidActiveTimeReader, mCpuUidClusterTimeReader,
+                mCpuUidFreqTimeReader, mCpuUidUserSysTimeReader);
     }
 
     private void updateTimeBasesLocked(boolean unplugged, int screenState,
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 dc93675..0771829 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -39,6 +39,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.Before;
@@ -54,7 +55,7 @@
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsImplTest {
     @Mock
-    private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
+    private KernelCpuUidFreqTimeReader mKernelUidCpuFreqTimeReader;
     @Mock
     private KernelSingleUidTimeReader mKernelSingleUidTimeReader;
 
@@ -67,7 +68,7 @@
         when(mKernelUidCpuFreqTimeReader.allUidTimesAvailable()).thenReturn(true);
         when(mKernelSingleUidTimeReader.singleUidCpuTimesAvailable()).thenReturn(true);
         mBatteryStatsImpl = new MockBatteryStatsImpl()
-                .setKernelUidCpuFreqTimeReader(mKernelUidCpuFreqTimeReader)
+                .setKernelCpuUidFreqTimeReader(mKernelUidCpuFreqTimeReader)
                 .setKernelSingleUidTimeReader(mKernelSingleUidTimeReader);
     }
 
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 d69e1d1..a6329298 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -38,7 +38,6 @@
         BatteryStatsTimerTest.class,
         BatteryStatsUidTest.class,
         BatteryStatsUserLifecycleTests.class,
-        KernelCpuProcReaderTest.class,
         KernelCpuProcStringReaderTest.class,
         KernelCpuUidActiveTimeReaderTest.class,
         KernelCpuUidClusterTimeReaderTest.class,
@@ -46,9 +45,6 @@
         KernelCpuUidUserSysTimeReaderTest.class,
         KernelMemoryBandwidthStatsTest.class,
         KernelSingleUidTimeReaderTest.class,
-        KernelUidCpuFreqTimeReaderTest.class,
-        KernelUidCpuActiveTimeReaderTest.class,
-        KernelUidCpuClusterTimeReaderTest.class,
         KernelWakelockReaderTest.class,
         LongSamplingCounterTest.class,
         LongSamplingCounterArrayTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
deleted file mode 100644
index a25a7489..0000000
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcReaderTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.os.FileUtils;
-import android.os.SystemClock;
-
-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.io.File;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.Random;
-
-/**
- * Test class for {@link KernelCpuProcReader}.
- *
- * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuProcReaderTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KernelCpuProcReaderTest {
-
-    private File mRoot;
-    private File mTestDir;
-    private File mTestFile;
-    private Random mRand = new Random();
-
-    private KernelCpuProcReader mKernelCpuProcReader;
-
-    private Context getContext() {
-        return InstrumentationRegistry.getContext();
-    }
-
-    @Before
-    public void setUp() {
-        mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
-        mRoot = getContext().getFilesDir();
-        mTestFile = new File(mTestDir, "test.file");
-        mKernelCpuProcReader = new KernelCpuProcReader(mTestFile.getAbsolutePath());
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        FileUtils.deleteContents(mTestDir);
-        FileUtils.deleteContents(mRoot);
-    }
-
-
-    /**
-     * Tests that reading will return null if the file does not exist.
-     */
-    @Test
-    public void testReadInvalidFile() throws Exception {
-        assertEquals(null, mKernelCpuProcReader.readBytes());
-    }
-
-    /**
-     * Tests that reading will always return null after 5 failures.
-     */
-    @Test
-    public void testReadErrorsLimit() throws Exception {
-        mKernelCpuProcReader.setThrottleInterval(0);
-        for (int i = 0; i < 3; i++) {
-            assertNull(mKernelCpuProcReader.readBytes());
-            SystemClock.sleep(50);
-        }
-
-        final byte[] data = new byte[1024];
-        mRand.nextBytes(data);
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-
-        assertTrue(mTestFile.delete());
-        for (int i = 0; i < 3; i++) {
-            assertNull(mKernelCpuProcReader.readBytes());
-            SystemClock.sleep(50);
-        }
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertNull(mKernelCpuProcReader.readBytes());
-    }
-
-    /**
-     * Tests reading functionality.
-     */
-    @Test
-    public void testSimpleRead() throws Exception {
-        final byte[] data = new byte[1024];
-        mRand.nextBytes(data);
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-    }
-
-    /**
-     * Tests multiple reading functionality.
-     */
-    @Test
-    public void testMultipleRead() throws Exception {
-        mKernelCpuProcReader.setThrottleInterval(0);
-        for (int i = 0; i < 100; i++) {
-            final byte[] data = new byte[mRand.nextInt(102400) + 4];
-            mRand.nextBytes(data);
-            try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-                os.write(data);
-            }
-            assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-            assertTrue(mTestFile.delete());
-        }
-    }
-
-    /**
-     * Tests reading with resizing.
-     */
-    @Test
-    public void testReadWithResize() throws Exception {
-        final byte[] data = new byte[128001];
-        mRand.nextBytes(data);
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-    }
-
-    /**
-     * Tests that reading a file over the limit (1MB) will return null.
-     */
-    @Test
-    public void testReadOverLimit() throws Exception {
-        final byte[] data = new byte[1228800];
-        mRand.nextBytes(data);
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertNull(mKernelCpuProcReader.readBytes());
-    }
-
-    /**
-     * Tests throttling. Deleting underlying file should not affect cache.
-     */
-    @Test
-    public void testThrottle() throws Exception {
-        mKernelCpuProcReader.setThrottleInterval(3000);
-        final byte[] data = new byte[20001];
-        mRand.nextBytes(data);
-        try (OutputStream os = Files.newOutputStream(mTestFile.toPath())) {
-            os.write(data);
-        }
-        assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-        assertTrue(mTestFile.delete());
-        for (int i = 0; i < 5; i++) {
-            assertTrue(Arrays.equals(data, toArray(mKernelCpuProcReader.readBytes())));
-            SystemClock.sleep(10);
-        }
-        SystemClock.sleep(5000);
-        assertNull(mKernelCpuProcReader.readBytes());
-    }
-
-    private byte[] toArray(ByteBuffer buffer) {
-        assertNotNull(buffer);
-        byte[] arr = new byte[buffer.remaining()];
-        buffer.get(arr);
-        return arr;
-    }
-}
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 7a31605..cbd2ba4 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
@@ -299,9 +299,10 @@
             assertTrue(mTestFile.delete());
             try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
                 w.write(data1);
-                modify.countDown();
             } catch (Throwable e) {
                 errs.add(e);
+            } finally {
+                modify.countDown();
             }
         }, 600, TimeUnit.MILLISECONDS);
 
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
deleted file mode 100644
index 12f6c18..0000000
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
+++ /dev/null
@@ -1,260 +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.internal.os;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import androidx.test.filters.SmallTest;
-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.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Random;
-
-/**
- * Test class for {@link KernelUidCpuActiveTimeReader}.
- *
- * To run it:
- * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuActiveTimeReaderTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KernelUidCpuActiveTimeReaderTest {
-    @Mock
-    private KernelCpuProcReader mProcReader;
-    @Mock
-    private KernelUidCpuActiveTimeReader.Callback mCallback;
-    private KernelUidCpuActiveTimeReader mReader;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mReader = new KernelUidCpuActiveTimeReader(mProcReader);
-        mReader.setThrottleInterval(0);
-    }
-
-    @Test
-    public void testReadDelta() {
-        final int cores = 8;
-        final int[] uids = {1, 22, 333, 4444, 5555};
-
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that a second call will only return deltas.
-        Mockito.reset(mCallback);
-        final long[][] times1 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times1));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times1[i], times[i])));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that there won't be a callback if the proc file values didn't change.
-        Mockito.reset(mCallback);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times1));
-        mReader.readDelta(mCallback);
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that calling with a null callback doesn't result in any crashes
-        Mockito.reset(mCallback);
-        final long[][] times2 = increaseTime(times1);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times2));
-        mReader.readDelta(null);
-
-        // Verify that the readDelta call will only return deltas when
-        // the previous call had null callback.
-        Mockito.reset(mCallback);
-        final long[][] times3 = increaseTime(times2);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times3));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; ++i) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
-        }
-        verifyNoMoreInteractions(mCallback);
-    }
-
-    @Test
-    public void testReadAbsolute() {
-        final int cores = 8;
-        final int[] uids = {1, 22, 333, 4444, 5555};
-
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
-        mReader.readAbsolute(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that a second call still returns absolute values
-        Mockito.reset(mCallback);
-        final long[][] times1 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times1));
-        mReader.readAbsolute(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times1[i]));
-        }
-        verifyNoMoreInteractions(mCallback);
-    }
-
-    @Test
-    public void testReadDelta_malformedData() {
-        final int cores = 8;
-        final int[] uids = {1, 22, 333, 4444, 5555};
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that there is no callback if subsequent call is in wrong format.
-        Mockito.reset(mCallback);
-        final long[][] times1 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times1).putInt(0, 5));
-        mReader.readDelta(mCallback);
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that the internal state was not modified if the given core count does not match
-        // the following # of entries.
-        Mockito.reset(mCallback);
-        final long[][] times2 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times2));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times2[i], times[i])));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that there is no callback if any value in the proc file is -ve.
-        Mockito.reset(mCallback);
-        final long[][] times3 = increaseTime(times2);
-        times3[uids.length - 1][cores - 1] *= -1;
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times3));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length - 1; ++i) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that the internal state was not modified when the proc file had -ve value.
-        Mockito.reset(mCallback);
-        for (int i = 0; i < cores; i++) {
-            times3[uids.length - 1][i] = times2[uids.length - 1][i] + uids[uids.length - 1] * 2520;
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times3));
-        mReader.readDelta(mCallback);
-        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1],
-                getTotal(subtract(times3[uids.length - 1], times2[uids.length - 1])));
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that there is no callback if the values in the proc file are decreased.
-        Mockito.reset(mCallback);
-        final long[][] times4 = increaseTime(times3);
-        System.arraycopy(times3[uids.length - 1], 0, times4[uids.length - 1], 0, cores);
-        times4[uids.length - 1][cores - 1] -= 100;
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times4));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length - 1; ++i) {
-            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times4[i], times3[i])));
-        }
-        verifyNoMoreInteractions(mCallback);
-
-        // Verify that the internal state was not modified when the proc file had decreased values.
-        Mockito.reset(mCallback);
-        for (int i = 0; i < cores; i++) {
-            times4[uids.length - 1][i] = times3[uids.length - 1][i] + uids[uids.length - 1] * 2520;
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times4));
-        mReader.readDelta(mCallback);
-        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1],
-                getTotal(subtract(times4[uids.length - 1], times3[uids.length - 1])));
-        verifyNoMoreInteractions(mCallback);
-    }
-
-    private long[] subtract(long[] a1, long[] a2) {
-        long[] val = new long[a1.length];
-        for (int i = 0; i < val.length; ++i) {
-            val[i] = a1[i] - a2[i];
-        }
-        return val;
-    }
-
-    /**
-     * Unit of original and return value is 10ms. What's special about 2520? 2520 is LCM of 1, 2, 3,
-     * ..., 10. So that when wedivide shared cpu time by concurrent thread count, we always get a
-     * nice integer, avoiding rounding errors.
-     */
-    private long[][] increaseTime(long[][] original) {
-        long[][] newTime = new long[original.length][original[0].length];
-        Random rand = new Random();
-        for (int i = 0; i < original.length; i++) {
-            for (int j = 0; j < original[0].length; j++) {
-                newTime[i][j] = original[i][j] + rand.nextInt(1000) * 2520 + 2520;
-            }
-        }
-        return newTime;
-    }
-
-    // Unit of times is 10ms
-    private long getTotal(long[] times) {
-        long sum = 0;
-        for (int i = 0; i < times.length; i++) {
-            sum += times[i] * 10 / (i + 1);
-        }
-        return sum;
-    }
-
-    /**
-     * Format uids and times (in 10ms) into the following format:
-     * [n, uid0, time0a, time0b, ..., time0n,
-     * uid1, time1a, time1b, ..., time1n,
-     * uid2, time2a, time2b, ..., time2n, etc.]
-     * where n is the total number of cpus (num_possible_cpus)
-     */
-    private ByteBuffer getUidTimesBytes(int[] uids, long[][] times) {
-        int size = (1 + uids.length * (times[0].length + 1)) * 4;
-        ByteBuffer buf = ByteBuffer.allocate(size);
-        buf.order(ByteOrder.nativeOrder());
-        buf.putInt(times[0].length);
-        for (int i = 0; i < uids.length; i++) {
-            buf.putInt(uids[i]);
-            for (int j = 0; j < times[i].length; j++) {
-                buf.putInt((int) times[i][j]);
-            }
-        }
-        buf.flip();
-        return buf.order(ByteOrder.nativeOrder());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
deleted file mode 100644
index 532f337..0000000
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
+++ /dev/null
@@ -1,326 +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.internal.os;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.when;
-
-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;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.Random;
-
-/**
- * Test class for {@link KernelUidCpuClusterTimeReader}.
- *
- * To run it:
- * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuClusterTimeReaderTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KernelUidCpuClusterTimeReaderTest {
-    @Mock
-    private KernelCpuProcReader mProcReader;
-    private KernelUidCpuClusterTimeReader mReader;
-    private VerifiableCallback mCallback;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mReader = new KernelUidCpuClusterTimeReader(mProcReader);
-        mCallback = new VerifiableCallback();
-        mReader.setThrottleInterval(0);
-    }
-
-    @Test
-    public void testReadDelta() throws Exception {
-        VerifiableCallback cb = new VerifiableCallback();
-        final int cores = 6;
-        final int[] clusters = {2, 4};
-        final int[] uids = {1, 22, 333, 4444, 5555};
-
-        // Verify initial call
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times));
-        mReader.readDelta(cb);
-        for (int i = 0; i < uids.length; i++) {
-            cb.verify(uids[i], getTotal(clusters, times[i]));
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that a second call will only return deltas.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times1 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times1));
-        mReader.readDelta(cb);
-        for (int i = 0; i < uids.length; i++) {
-            cb.verify(uids[i], getTotal(clusters, subtract(times1[i], times[i])));
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that there won't be a callback if the proc file values didn't change.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times1));
-        mReader.readDelta(cb);
-        cb.verifyNoMoreInteractions();
-
-        // Verify that calling with a null callback doesn't result in any crashes
-        Mockito.reset(mProcReader);
-        final long[][] times2 = increaseTime(times1);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times2));
-        mReader.readDelta(null);
-
-        // Verify that the readDelta call will only return deltas when
-        // the previous call had null callback.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times3 = increaseTime(times2);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times3));
-        mReader.readDelta(cb);
-        for (int i = 0; i < uids.length; i++) {
-            cb.verify(uids[i], getTotal(clusters, subtract(times3[i], times2[i])));
-        }
-        cb.verifyNoMoreInteractions();
-
-    }
-
-    @Test
-    public void testReadAbsolute() throws Exception {
-        VerifiableCallback cb = new VerifiableCallback();
-        final int cores = 6;
-        final int[] clusters = {2, 4};
-        final int[] uids = {1, 22, 333, 4444, 5555};
-
-        // Verify return absolute value
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times));
-        mReader.readAbsolute(cb);
-        for (int i = 0; i < uids.length; i++) {
-            cb.verify(uids[i], getTotal(clusters, times[i]));
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that a second call should return the same absolute value
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times1 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times1));
-        mReader.readAbsolute(cb);
-        for (int i = 0; i < uids.length; i++) {
-            cb.verify(uids[i], getTotal(clusters, times1[i]));
-        }
-        cb.verifyNoMoreInteractions();
-    }
-
-    @Test
-    public void testReadDelta_malformedData() throws Exception {
-        final int cores = 6;
-        final int[] clusters = {2, 4};
-        final int[] uids = {1, 22, 333, 4444, 5555};
-
-        // Verify initial call
-        final long[][] times = increaseTime(new long[uids.length][cores]);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            mCallback.verify(uids[i], getTotal(clusters, times[i]));
-        }
-        mCallback.verifyNoMoreInteractions();
-
-        // Verify that there is no callback if a call has wrong format
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        final long[][] temp = increaseTime(times);
-        final long[][] times1 = new long[uids.length][];
-        for (int i = 0; i < temp.length; i++) {
-            times1[i] = Arrays.copyOfRange(temp[i], 0, 4);
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times1));
-        mReader.readDelta(mCallback);
-        mCallback.verifyNoMoreInteractions();
-
-        // Verify that the internal state was not modified if the given core count does not match
-        // the following # of entries.
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times2 = increaseTime(times);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times2));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length; i++) {
-            mCallback.verify(uids[i], getTotal(clusters, subtract(times2[i], times[i])));
-        }
-        mCallback.verifyNoMoreInteractions();
-
-        // Verify that there is no callback if any value in the proc file is -ve.
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times3 = increaseTime(times2);
-        times3[uids.length - 1][cores - 1] *= -1;
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times3));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length - 1; i++) {
-            mCallback.verify(uids[i], getTotal(clusters, subtract(times3[i], times2[i])));
-        }
-        mCallback.verifyNoMoreInteractions();
-
-        // Verify that the internal state was not modified when the proc file had -ve value.
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        for (int i = 0; i < cores; i++) {
-            times3[uids.length - 1][i] = times2[uids.length - 1][i] + uids[uids.length - 1] * 2520;
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times3));
-        mReader.readDelta(mCallback);
-        mCallback.verify(uids[uids.length - 1],
-                getTotal(clusters, subtract(times3[uids.length - 1], times2[uids.length - 1])));
-
-        // Verify that there is no callback if the values in the proc file are decreased.
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        final long[][] times4 = increaseTime(times3);
-        System.arraycopy(times3[uids.length - 1], 0, times4[uids.length - 1], 0, cores);
-        times4[uids.length - 1][cores - 1] -= 100;
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times4));
-        mReader.readDelta(mCallback);
-        for (int i = 0; i < uids.length - 1; i++) {
-            mCallback.verify(uids[i], getTotal(clusters, subtract(times4[i], times3[i])));
-        }
-        mCallback.verifyNoMoreInteractions();
-
-        // Verify that the internal state was not modified when the proc file had decreased values.
-        mCallback.clear();
-        Mockito.reset(mProcReader);
-        for (int i = 0; i < cores; i++) {
-            times4[uids.length - 1][i] = times3[uids.length - 1][i] + uids[uids.length - 1] * 2520;
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, clusters, times4));
-        mReader.readDelta(mCallback);
-        mCallback.verify(uids[uids.length - 1],
-                getTotal(clusters, subtract(times3[uids.length - 1], times2[uids.length - 1])));
-        mCallback.verifyNoMoreInteractions();
-    }
-
-
-    private long[] subtract(long[] a1, long[] a2) {
-        long[] val = new long[a1.length];
-        for (int i = 0; i < val.length; ++i) {
-            val[i] = a1[i] - a2[i];
-        }
-        return val;
-    }
-
-    /**
-     * Unit is 10ms. What's special about 2520? 2520 is LCM of 1, 2, 3, ..., 10. So that when we
-     * divide shared cpu time by concurrent thread count, we always get a nice integer, avoiding
-     * rounding errors.
-     */
-    private long[][] increaseTime(long[][] original) {
-        long[][] newTime = new long[original.length][original[0].length];
-        Random rand = new Random();
-        for (int i = 0; i < original.length; i++) {
-            for (int j = 0; j < original[0].length; j++) {
-                newTime[i][j] = original[i][j] + rand.nextInt(1000) * 2520 + 2520;
-            }
-        }
-        return newTime;
-    }
-
-    // Format an array of cluster times according to the algorithm in KernelUidCpuClusterTimeReader
-    private long[] getTotal(int[] cluster, long[] times) {
-        int core = 0;
-        long[] sumTimes = new long[cluster.length];
-        for (int i = 0; i < cluster.length; i++) {
-            double sum = 0;
-            for (int j = 0; j < cluster[i]; j++) {
-                sum += (double) times[core++] * 10 / (j + 1);
-            }
-            sumTimes[i] = (long) sum;
-        }
-        return sumTimes;
-    }
-
-    private class VerifiableCallback implements KernelUidCpuClusterTimeReader.Callback {
-
-        SparseArray<long[]> mData = new SparseArray<>();
-        int count = 0;
-
-        public void verify(int uid, long[] cpuClusterTimeMs) {
-            long[] array = mData.get(uid);
-            assertNotNull(array);
-            assertArrayEquals(cpuClusterTimeMs, array);
-            count++;
-        }
-
-        public void clear() {
-            mData.clear();
-            count = 0;
-        }
-
-        @Override
-        public void onUidCpuPolicyTime(int uid, long[] cpuClusterTimeMs) {
-            long[] array = new long[cpuClusterTimeMs.length];
-            System.arraycopy(cpuClusterTimeMs, 0, array, 0, array.length);
-            mData.put(uid, array);
-        }
-
-        public void verifyNoMoreInteractions() {
-            assertEquals(mData.size(), count);
-        }
-    }
-
-    /**
-     * Format uids and times (in 10ms) into the following format:
-     * [n, x0, ..., xn, uid0, time0a, time0b, ..., time0n,
-     * uid1, time1a, time1b, ..., time1n,
-     * uid2, time2a, time2b, ..., time2n, etc.]
-     * where n is the number of policies
-     * xi is the number cpus on a particular policy
-     */
-    private ByteBuffer getUidTimesBytes(int[] uids, int[] clusters, long[][] times) {
-        int size = (1 + clusters.length + uids.length * (times[0].length + 1)) * 4;
-        ByteBuffer buf = ByteBuffer.allocate(size);
-        buf.order(ByteOrder.nativeOrder());
-        buf.putInt(clusters.length);
-        for (int i = 0; i < clusters.length; i++) {
-            buf.putInt(clusters[i]);
-        }
-        for (int i = 0; i < uids.length; i++) {
-            buf.putInt(uids[i]);
-            for (int j = 0; j < times[i].length; j++) {
-                buf.putInt((int) (times[i][j]));
-            }
-        }
-        buf.flip();
-        return buf.order(ByteOrder.nativeOrder());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
deleted file mode 100644
index 6d2980b..0000000
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ /dev/null
@@ -1,331 +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.internal.os;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-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;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.BufferedReader;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-
-/**
- * Test class for {@link KernelUidCpuFreqTimeReader}.
- *
- * To run the tests, use
- *
- * runtest -c com.android.internal.os.KernelUidCpuFreqTimeReaderTest frameworks-core
- *
- * or the following steps:
- *
- * Build: m FrameworksCoreTests
- * 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/androidx.test.runner.AndroidJUnitRunner
- *
- * or
- *
- * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuFreqTimeReaderTest
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KernelUidCpuFreqTimeReaderTest {
-    @Mock
-    private BufferedReader mBufferedReader;
-    @Mock
-    private KernelUidCpuFreqTimeReader.Callback mCallback;
-    @Mock
-    private PowerProfile mPowerProfile;
-    @Mock
-    private KernelCpuProcReader mProcReader;
-
-    private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mKernelUidCpuFreqTimeReader = new KernelUidCpuFreqTimeReader(mProcReader);
-        mKernelUidCpuFreqTimeReader.setThrottleInterval(0);
-    }
-
-    @Test
-    public void testReadFreqs_perClusterTimesNotAvailable() throws Exception {
-        final long[][] freqs = {
-                {1, 12, 123, 1234},
-                {1, 12, 123, 23, 123, 1234, 12345, 123456},
-                {1, 12, 123, 23, 123, 1234, 12345, 123456, 12, 123, 12345},
-                {1, 12, 123, 23, 2345, 234567}
-        };
-        final int[] numClusters = {2, 2, 3, 1};
-        final int[][] numFreqs = {{3, 6}, {4, 5}, {3, 5, 4}, {3}};
-        for (int i = 0; i < freqs.length; ++i) {
-            setCpuClusterFreqs(numClusters[i], numFreqs[i]);
-            when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs[i]));
-            long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(
-                    mBufferedReader, mPowerProfile);
-            assertArrayEquals(freqs[i], actualFreqs);
-            verifyZeroInteractions(mCallback);
-            final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
-                    Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
-            assertFalse(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
-
-            // Verify that a second call won't read the proc file again
-            Mockito.reset(mBufferedReader);
-            actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
-            assertArrayEquals(freqs[i], actualFreqs);
-            assertFalse(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
-
-            // Prepare for next iteration
-            Mockito.reset(mBufferedReader, mPowerProfile);
-        }
-    }
-
-    @Test
-    public void testReadFreqs_perClusterTimesAvailable() throws Exception {
-        final long[][] freqs = {
-                {1, 12, 123, 1234},
-                {1, 12, 123, 23, 123, 1234, 12345, 123456},
-                {1, 12, 123, 23, 123, 1234, 12345, 123456, 12, 123, 12345, 1234567}
-        };
-        final int[] numClusters = {1, 2, 3};
-        final int[][] numFreqs = {{4}, {3, 5}, {3, 5, 4}};
-        for (int i = 0; i < freqs.length; ++i) {
-            setCpuClusterFreqs(numClusters[i], numFreqs[i]);
-            when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs[i]));
-            long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(
-                    mBufferedReader, mPowerProfile);
-            assertArrayEquals(freqs[i], actualFreqs);
-            verifyZeroInteractions(mCallback);
-            final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
-                    Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
-            assertTrue(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
-
-            // Verify that a second call won't read the proc file again
-            Mockito.reset(mBufferedReader);
-            actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mPowerProfile);
-            assertArrayEquals(freqs[i], actualFreqs);
-            assertTrue(errMsg, mKernelUidCpuFreqTimeReader.perClusterTimesAvailable());
-
-            // Prepare for next iteration
-            Mockito.reset(mBufferedReader, mPowerProfile);
-        }
-    }
-
-    @Test
-    public void testReadDelta_Binary() throws Exception {
-        VerifiableCallback cb = new VerifiableCallback();
-        final long[] freqs = {110, 123, 145, 167, 289, 997};
-        final int[] uids = {1, 22, 333, 444, 555};
-        final long[][] times = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                times[i][j] = uids[i] * freqs[j] * 10;
-            }
-        }
-        when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs));
-        long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mBufferedReader, mPowerProfile);
-
-        assertArrayEquals(freqs, actualFreqs);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
-        mKernelUidCpuFreqTimeReader.readDeltaImpl(cb);
-        for (int i = 0; i < uids.length; ++i) {
-            cb.verify(uids[i], times[i]);
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that a second call will only return deltas.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] newTimes1 = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                newTimes1[i][j] = times[i][j] + (uids[i] + freqs[j]) * 50;
-            }
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes1));
-        mKernelUidCpuFreqTimeReader.readDeltaImpl(cb);
-        for (int i = 0; i < uids.length; ++i) {
-            cb.verify(uids[i], subtract(newTimes1[i], times[i]));
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that there won't be a callback if the proc file values didn't change.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes1));
-        mKernelUidCpuFreqTimeReader.readDeltaImpl(cb);
-        cb.verifyNoMoreInteractions();
-
-        // Verify that calling with a null callback doesn't result in any crashes
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] newTimes2 = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                newTimes2[i][j] = newTimes1[i][j] + (uids[i] * freqs[j]) * 30;
-            }
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes2));
-        mKernelUidCpuFreqTimeReader.readDeltaImpl(null);
-        cb.verifyNoMoreInteractions();
-
-        // Verify that the readDelta call will only return deltas when
-        // the previous call had null callback.
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] newTimes3 = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                newTimes3[i][j] = newTimes2[i][j] + (uids[i] + freqs[j]) * 40;
-            }
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes3));
-        mKernelUidCpuFreqTimeReader.readDeltaImpl(cb);
-        for (int i = 0; i < uids.length; ++i) {
-            cb.verify(uids[i], subtract(newTimes3[i], newTimes2[i]));
-        }
-        cb.verifyNoMoreInteractions();
-    }
-
-    @Test
-    public void testReadAbsolute() throws Exception {
-        VerifiableCallback cb = new VerifiableCallback();
-        final long[] freqs = {110, 123, 145, 167, 289, 997};
-        final int[] uids = {1, 22, 333, 444, 555};
-        final long[][] times = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                times[i][j] = uids[i] * freqs[j] * 10;
-            }
-        }
-        when(mBufferedReader.readLine()).thenReturn(getFreqsLine(freqs));
-        long[] actualFreqs = mKernelUidCpuFreqTimeReader.readFreqs(mBufferedReader, mPowerProfile);
-
-        assertArrayEquals(freqs, actualFreqs);
-        // Verify that the absolute values are returned
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, times));
-        mKernelUidCpuFreqTimeReader.readAbsolute(cb);
-        for (int i = 0; i < uids.length; ++i) {
-            cb.verify(uids[i], times[i]);
-        }
-        cb.verifyNoMoreInteractions();
-
-        // Verify that a second call should still return absolute values
-        cb.clear();
-        Mockito.reset(mProcReader);
-        final long[][] newTimes1 = new long[uids.length][freqs.length];
-        for (int i = 0; i < uids.length; ++i) {
-            for (int j = 0; j < freqs.length; ++j) {
-                newTimes1[i][j] = times[i][j] + (uids[i] + freqs[j]) * 50;
-            }
-        }
-        when(mProcReader.readBytes()).thenReturn(getUidTimesBytes(uids, newTimes1));
-        mKernelUidCpuFreqTimeReader.readAbsolute(cb);
-        for (int i = 0; i < uids.length; ++i) {
-            cb.verify(uids[i], newTimes1[i]);
-        }
-        cb.verifyNoMoreInteractions();
-    }
-
-    private long[] subtract(long[] a1, long[] a2) {
-        long[] val = new long[a1.length];
-        for (int i = 0; i < val.length; ++i) {
-            val[i] = a1[i] - a2[i];
-        }
-        return val;
-    }
-
-    private String getFreqsLine(long[] freqs) {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("uid:");
-        for (int i = 0; i < freqs.length; ++i) {
-            sb.append(" " + freqs[i]);
-        }
-        return sb.toString();
-    }
-
-    private ByteBuffer getUidTimesBytes(int[] uids, long[][] times) {
-        int size = (1 + uids.length + uids.length * times[0].length) * 4;
-        ByteBuffer buf = ByteBuffer.allocate(size);
-        buf.order(ByteOrder.nativeOrder());
-        buf.putInt(times[0].length);
-        for (int i = 0; i < uids.length; i++) {
-            buf.putInt(uids[i]);
-            for (int j = 0; j < times[i].length; j++) {
-                buf.putInt((int) (times[i][j] / 10));
-            }
-        }
-        buf.flip();
-        return buf.asReadOnlyBuffer().order(ByteOrder.nativeOrder());
-    }
-
-    private void setCpuClusterFreqs(int numClusters, int... clusterFreqs) {
-        assertEquals(numClusters, clusterFreqs.length);
-        when(mPowerProfile.getNumCpuClusters()).thenReturn(numClusters);
-        for (int i = 0; i < numClusters; ++i) {
-            when(mPowerProfile.getNumSpeedStepsInCpuCluster(i)).thenReturn(clusterFreqs[i]);
-        }
-    }
-
-    private class VerifiableCallback implements KernelUidCpuFreqTimeReader.Callback {
-
-        SparseArray<long[]> mData = new SparseArray<>();
-        int count = 0;
-
-        public void verify(int uid, long[] cpuFreqTimeMs) {
-            long[] array = mData.get(uid);
-            assertNotNull(array);
-            assertArrayEquals(cpuFreqTimeMs, array);
-            count++;
-        }
-
-        public void clear() {
-            mData.clear();
-            count = 0;
-        }
-
-        @Override
-        public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
-            long[] array = new long[cpuFreqTimeMs.length];
-            System.arraycopy(cpuFreqTimeMs, 0, array, 0, array.length);
-            mData.put(uid, array);
-        }
-
-        public void verifyNoMoreInteractions() {
-            assertEquals(mData.size(), count);
-        }
-    }
-}
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 c18445e..bc0e0a4 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,10 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.location.gnssmetrics.GnssMetrics;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 
 import java.util.ArrayList;
 import java.util.Queue;
@@ -43,13 +47,14 @@
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
         setExternalStatsSyncLocked(new DummyExternalStatsSync());
 
-        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
-            mGpsSignalQualityTimer[i] = new StopwatchTimer(clocks, null, -1000-i, null,
-                mOnBatteryTimeBase);
+        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(clocks, null, -1000 - i, null,
+                    mOnBatteryTimeBase);
         }
 
         // A no-op handler.
-        mHandler = new Handler(Looper.getMainLooper()) {};
+        mHandler = new Handler(Looper.getMainLooper()) {
+        };
     }
 
     MockBatteryStatsImpl() {
@@ -95,23 +100,26 @@
         return this;
     }
 
-    public MockBatteryStatsImpl setKernelUidCpuFreqTimeReader(KernelUidCpuFreqTimeReader reader) {
-        mKernelUidCpuFreqTimeReader = reader;
+    public MockBatteryStatsImpl setKernelCpuUidFreqTimeReader(KernelCpuUidFreqTimeReader reader) {
+        mCpuUidFreqTimeReader = reader;
         return this;
     }
 
-    public MockBatteryStatsImpl setKernelUidCpuActiveTimeReader(KernelUidCpuActiveTimeReader reader) {
-        mKernelUidCpuActiveTimeReader = reader;
+    public MockBatteryStatsImpl setKernelCpuUidActiveTimeReader(
+            KernelCpuUidActiveTimeReader reader) {
+        mCpuUidActiveTimeReader = reader;
         return this;
     }
 
-    public MockBatteryStatsImpl setKernelUidCpuClusterTimeReader(KernelUidCpuClusterTimeReader reader) {
-        mKernelUidCpuClusterTimeReader = reader;
+    public MockBatteryStatsImpl setKernelCpuUidClusterTimeReader(
+            KernelCpuUidClusterTimeReader reader) {
+        mCpuUidClusterTimeReader = reader;
         return this;
     }
 
-    public MockBatteryStatsImpl setKernelUidCpuTimeReader(KernelUidCpuTimeReader reader) {
-        mKernelUidCpuTimeReader = reader;
+    public MockBatteryStatsImpl setKernelCpuUidUserSysTimeReader(
+            KernelCpuUidUserSysTimeReader reader) {
+        mCpuUidUserSysTimeReader = reader;
         return this;
     }
 
diff --git a/core/tests/hdmitests/Android.mk b/core/tests/hdmitests/Android.mk
index 2ca31a6..f155feb 100644
--- a/core/tests/hdmitests/Android.mk
+++ b/core/tests/hdmitests/Android.mk
@@ -20,7 +20,7 @@
 # Include all test java files
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils
+LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils truth-prebuilt
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := HdmiCecTests
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiUtilsTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiUtilsTest.java
new file mode 100644
index 0000000..fdc6b84
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiUtilsTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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 androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+/**
+ * Tests for {@link HdmiUtils}.
+ */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiUtilsTest {
+    @Test
+    public void testInvalidAddress() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0, -1))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0xFFFF, 0xFFFF))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0xFFFFF, 0))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN);
+    }
+
+    @Test
+    public void testSameAddress() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1000))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SAME);
+    }
+
+    @Test
+    public void testDirectlyAbove() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1200))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
+    }
+
+    @Test
+    public void testDirectlyAbove_rootDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x0000, 0x2000))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
+    }
+
+    @Test
+    public void testDirectlyAbove_leafDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1240, 0x1245))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_ABOVE);
+    }
+
+    @Test
+    public void testAbove() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x1000, 0x1210))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_ABOVE);
+    }
+
+    @Test
+    public void testAbove_rootDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x0000, 0x1200))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_ABOVE);
+    }
+
+    @Test
+    public void testDirectlyBelow() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x2250, 0x2200))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
+    }
+
+    @Test
+    public void testDirectlyBelow_rootDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x5000, 0x0000))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
+    }
+
+    @Test
+    public void testDirectlyBelow_leafDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x3249, 0x3240))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW);
+    }
+
+    @Test
+    public void testBelow() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x5143, 0x5100))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_BELOW);
+    }
+
+    @Test
+    public void testBelow_rootDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x3420, 0x0000))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_BELOW);
+    }
+
+    @Test
+    public void testSibling() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x4000, 0x5000))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SIBLING);
+    }
+
+    @Test
+    public void testSibling_leafDevice() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x798A, 0x798F))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_SIBLING);
+    }
+
+    @Test
+    public void testDifferentBranch() {
+        assertThat(HdmiUtils.getHdmiAddressRelativePosition(0x798A, 0x7970))
+                .isEqualTo(HdmiUtils.HDMI_RELATIVE_POSITION_DIFFERENT_BRANCH);
+    }
+
+    @Test
+    public void isValidPysicalAddress_true() {
+        assertThat(HdmiUtils.isValidPhysicalAddress(0)).isTrue();
+        assertThat(HdmiUtils.isValidPhysicalAddress(0xFFFE)).isTrue();
+        assertThat(HdmiUtils.isValidPhysicalAddress(0x1200)).isTrue();
+    }
+
+    @Test
+    public void isValidPysicalAddress_outOfRange() {
+        assertThat(HdmiUtils.isValidPhysicalAddress(-1)).isFalse();
+        assertThat(HdmiUtils.isValidPhysicalAddress(0xFFFF)).isFalse();
+        assertThat(HdmiUtils.isValidPhysicalAddress(0x10000)).isFalse();
+    }
+
+    @Test
+    public void isValidPysicalAddress_nonTrailingZeros() {
+        assertThat(HdmiUtils.isValidPhysicalAddress(0x0001)).isFalse();
+        assertThat(HdmiUtils.isValidPhysicalAddress(0x0213)).isFalse();
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ActivityChangedEvent.java b/location/lib/java/com/android/location/provider/ActivityChangedEvent.java
new file mode 100644
index 0000000..843dd67
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ActivityChangedEvent.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.annotation.NonNull;
+
+import java.security.InvalidParameterException;
+import java.util.List;
+
+/**
+ * A class representing an event for Activity changes.
+ * @hide
+ */
+public class ActivityChangedEvent {
+    private final List<ActivityRecognitionEvent> mActivityRecognitionEvents;
+
+    public ActivityChangedEvent(List<ActivityRecognitionEvent> activityRecognitionEvents) {
+        if (activityRecognitionEvents == null) {
+            throw new InvalidParameterException(
+                    "Parameter 'activityRecognitionEvents' must not be null.");
+        }
+
+        mActivityRecognitionEvents = activityRecognitionEvents;
+    }
+
+    @NonNull
+    public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() {
+        return mActivityRecognitionEvents;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("[ ActivityChangedEvent:");
+
+        for (ActivityRecognitionEvent event : mActivityRecognitionEvents) {
+            builder.append("\n    ");
+            builder.append(event.toString());
+        }
+        builder.append("\n]");
+
+        return builder.toString();
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java b/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java
new file mode 100644
index 0000000..e54dea4
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.android.location.provider;
+
+/**
+ * A class that represents an Activity Recognition Event.
+ * @hide
+ */
+public class ActivityRecognitionEvent {
+    private final String mActivity;
+    private final int mEventType;
+    private final long mTimestampNs;
+
+    public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) {
+        mActivity = activity;
+        mEventType = eventType;
+        mTimestampNs = timestampNs;
+    }
+
+    public String getActivity() {
+        return mActivity;
+    }
+
+    public int getEventType() {
+        return mEventType;
+    }
+
+    public long getTimestampNs() {
+        return mTimestampNs;
+    }
+
+    @Override
+    public String toString() {
+        String eventString;
+        switch (mEventType) {
+            case ActivityRecognitionProvider.EVENT_TYPE_ENTER:
+                eventString = "Enter";
+                break;
+            case ActivityRecognitionProvider.EVENT_TYPE_EXIT:
+                eventString = "Exit";
+                break;
+            case ActivityRecognitionProvider.EVENT_TYPE_FLUSH_COMPLETE:
+                eventString = "FlushComplete";
+                break;
+            default:
+                eventString = "<Invalid>";
+                break;
+        }
+
+        return String.format(
+                "Activity='%s', EventType=%s(%s), TimestampNs=%s",
+                mActivity,
+                eventString,
+                mEventType,
+                mTimestampNs);
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
new file mode 100644
index 0000000..0eff7d3
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
@@ -0,0 +1,133 @@
+/*
+ * 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 com.android.location.provider;
+
+import com.android.internal.util.Preconditions;
+
+import android.hardware.location.IActivityRecognitionHardware;
+import android.hardware.location.IActivityRecognitionHardwareSink;
+import android.os.RemoteException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services.
+ * @hide
+ */
+public final class ActivityRecognitionProvider {
+    private final IActivityRecognitionHardware mService;
+    private final HashSet<Sink> mSinkSet = new HashSet<>();
+
+    // the following constants must remain in sync with activity_recognition.h
+
+    public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle";
+    public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle";
+    public static final String ACTIVITY_WALKING = "android.activity_recognition.walking";
+    public static final String ACTIVITY_RUNNING = "android.activity_recognition.running";
+    public static final String ACTIVITY_STILL = "android.activity_recognition.still";
+    public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";
+
+    // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in
+    // android.hardware.location.ActivityRecognitionHardware
+    public static final int EVENT_TYPE_FLUSH_COMPLETE = 0;
+    public static final int EVENT_TYPE_ENTER = 1;
+    public static final int EVENT_TYPE_EXIT = 2;
+
+    // end constants activity_recognition.h
+
+    /**
+     * Used to receive Activity-Recognition events.
+     */
+    public interface Sink {
+        void onActivityChanged(ActivityChangedEvent event);
+    }
+
+    public ActivityRecognitionProvider(IActivityRecognitionHardware service)
+            throws RemoteException {
+        Preconditions.checkNotNull(service);
+        mService = service;
+        mService.registerSink(new SinkTransport());
+    }
+
+    public String[] getSupportedActivities() throws RemoteException {
+        return mService.getSupportedActivities();
+    }
+
+    public boolean isActivitySupported(String activity) throws RemoteException {
+        return mService.isActivitySupported(activity);
+    }
+
+    public void registerSink(Sink sink) {
+        Preconditions.checkNotNull(sink);
+        synchronized (mSinkSet) {
+            mSinkSet.add(sink);
+        }
+    }
+
+    // TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here
+    // and in the service) of all sinks while failing to disable all events
+    public void unregisterSink(Sink sink) {
+        Preconditions.checkNotNull(sink);
+        synchronized (mSinkSet) {
+            mSinkSet.remove(sink);
+        }
+    }
+
+    public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs)
+            throws RemoteException {
+        return mService.enableActivityEvent(activity, eventType, reportLatencyNs);
+    }
+
+    public boolean disableActivityEvent(String activity, int eventType) throws RemoteException {
+        return mService.disableActivityEvent(activity, eventType);
+    }
+
+    public boolean flush() throws RemoteException {
+        return mService.flush();
+    }
+
+    private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub {
+        @Override
+        public void onActivityChanged(android.hardware.location.ActivityChangedEvent event) {
+            Collection<Sink> sinks;
+            synchronized (mSinkSet) {
+                if (mSinkSet.isEmpty()) {
+                    return;
+                }
+                sinks = new ArrayList<>(mSinkSet);
+            }
+
+            // translate the event from platform internal and GmsCore types
+            ArrayList<ActivityRecognitionEvent> gmsEvents = new ArrayList<>();
+            for (android.hardware.location.ActivityRecognitionEvent reportingEvent
+                    : event.getActivityRecognitionEvents()) {
+                ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent(
+                        reportingEvent.getActivity(),
+                        reportingEvent.getEventType(),
+                        reportingEvent.getTimestampNs());
+                gmsEvents.add(gmsEvent);
+            }
+            ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents);
+
+            for (Sink sink : sinks) {
+                sink.onActivityChanged(gmsEvent);
+            }
+        }
+    }
+}
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java
new file mode 100644
index 0000000..326d901
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java
@@ -0,0 +1,76 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.annotation.NonNull;
+import android.hardware.location.IActivityRecognitionHardware;
+import android.hardware.location.IActivityRecognitionHardwareClient;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A client class for interaction with an Activity-Recognition provider.
+ * @hide
+ */
+public abstract class ActivityRecognitionProviderClient {
+    private static final String TAG = "ArProviderClient";
+
+    protected ActivityRecognitionProviderClient() {}
+
+    private IActivityRecognitionHardwareClient.Stub mClient =
+            new IActivityRecognitionHardwareClient.Stub() {
+                @Override
+                public void onAvailabilityChanged(
+                        boolean isSupported,
+                        IActivityRecognitionHardware instance) {
+                    int callingUid = Binder.getCallingUid();
+                    if (callingUid != Process.SYSTEM_UID) {
+                        Log.d(TAG, "Ignoring calls from non-system server. Uid: " + callingUid);
+                        return;
+                    }
+                    ActivityRecognitionProvider provider;
+                    try {
+                        provider = isSupported ? new ActivityRecognitionProvider(instance) : null;
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error creating Hardware Activity-Recognition Provider.", e);
+                        return;
+                    }
+                    onProviderChanged(isSupported, provider);
+                }
+            };
+
+    /**
+     * Gets the binder needed to interact with proxy provider in the platform.
+     */
+    @NonNull
+    public IBinder getBinder() {
+        return mClient;
+    }
+
+    /**
+     * Called when a change in the availability of {@link ActivityRecognitionProvider} is detected.
+     *
+     * @param isSupported whether the platform supports the provider natively
+     * @param instance the available provider's instance
+     */
+    public abstract void onProviderChanged(
+            boolean isSupported,
+            ActivityRecognitionProvider instance);
+}
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java
new file mode 100644
index 0000000..42f77b4
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java
@@ -0,0 +1,90 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.location.IActivityRecognitionHardware;
+import android.hardware.location.IActivityRecognitionHardwareWatcher;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A watcher class for Activity-Recognition instances.
+ *
+ * @deprecated use {@link ActivityRecognitionProviderClient} instead.
+ * @hide
+ */
+@Deprecated
+public class ActivityRecognitionProviderWatcher {
+    private static final String TAG = "ActivityRecognitionProviderWatcher";
+
+    private static ActivityRecognitionProviderWatcher sWatcher;
+    private static final Object sWatcherLock = new Object();
+
+    private ActivityRecognitionProvider mActivityRecognitionProvider;
+
+    private ActivityRecognitionProviderWatcher() {}
+
+    public static ActivityRecognitionProviderWatcher getInstance() {
+        synchronized (sWatcherLock) {
+            if (sWatcher == null) {
+                sWatcher = new ActivityRecognitionProviderWatcher();
+            }
+            return sWatcher;
+        }
+    }
+
+    private IActivityRecognitionHardwareWatcher.Stub mWatcherStub =
+            new IActivityRecognitionHardwareWatcher.Stub() {
+        @Override
+        public void onInstanceChanged(IActivityRecognitionHardware instance) {
+            int callingUid = Binder.getCallingUid();
+            if (callingUid != Process.SYSTEM_UID) {
+                Log.d(TAG, "Ignoring calls from non-system server. Uid: " + callingUid);
+                return;
+            }
+
+            try {
+                mActivityRecognitionProvider = new ActivityRecognitionProvider(instance);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error creating Hardware Activity-Recognition", e);
+            }
+        }
+    };
+
+    /**
+     * Gets the binder needed to interact with proxy provider in the platform.
+     */
+    @NonNull
+    public IBinder getBinder() {
+        return mWatcherStub;
+    }
+
+    /**
+     * Gets an object that supports the functionality of {@link ActivityRecognitionProvider}.
+     *
+     * @return Non-null value if the functionality is supported by the platform, false otherwise.
+     */
+    @Nullable
+    public ActivityRecognitionProvider getActivityRecognitionProvider() {
+        return mActivityRecognitionProvider;
+    }
+}
diff --git a/lowpan/tests/Android.mk b/lowpan/tests/Android.mk
index 67727a7..832ed2f 100644
--- a/lowpan/tests/Android.mk
+++ b/lowpan/tests/Android.mk
@@ -45,7 +45,7 @@
 LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-	android-support-test \
+	androidx.test.rules \
 	guava \
 	mockito-target-minus-junit4 \
 	frameworks-base-testutils \
diff --git a/lowpan/tests/AndroidManifest.xml b/lowpan/tests/AndroidManifest.xml
index a216214..4225613 100644
--- a/lowpan/tests/AndroidManifest.xml
+++ b/lowpan/tests/AndroidManifest.xml
@@ -30,7 +30,7 @@
         </activity>
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="android.net.lowpan.test"
         android:label="Frameworks LoWPAN API Tests">
     </instrumentation>
diff --git a/lowpan/tests/AndroidTest.xml b/lowpan/tests/AndroidTest.xml
index 72ad050..978cc02 100644
--- a/lowpan/tests/AndroidTest.xml
+++ b/lowpan/tests/AndroidTest.xml
@@ -22,6 +22,6 @@
     <option name="test-tag" value="FrameworksLowpanApiTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="android.net.lowpan.test" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
 </configuration>
diff --git a/lowpan/tests/README.md b/lowpan/tests/README.md
index d0eed95..cb5772e 100644
--- a/lowpan/tests/README.md
+++ b/lowpan/tests/README.md
@@ -37,7 +37,7 @@
 If you manually build and push the test APK to the device you can run tests using
 
 ```
-adb shell am instrument -w 'android.net.wifi.test/android.support.test.runner.AndroidJUnitRunner'
+adb shell am instrument -w 'android.net.wifi.test/androidx.test.runner.AndroidJUnitRunner'
 ```
 
 ## Adding Tests
diff --git a/lowpan/tests/runtests.sh b/lowpan/tests/runtests.sh
index 040f4f0..8267a79 100755
--- a/lowpan/tests/runtests.sh
+++ b/lowpan/tests/runtests.sh
@@ -21,4 +21,4 @@
 
 adb install -r -g "$OUT/data/app/FrameworksLowpanApiTests/FrameworksLowpanApiTests.apk"
 
-adb shell am instrument -w "$@" 'android.net.lowpan.test/android.support.test.runner.AndroidJUnitRunner'
+adb shell am instrument -w "$@" 'android.net.lowpan.test/androidx.test.runner.AndroidJUnitRunner'
diff --git a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java b/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java
index a495d3d..86f9d0e 100644
--- a/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java
+++ b/lowpan/tests/src/android/net/lowpan/LowpanInterfaceTest.java
@@ -23,15 +23,18 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.test.TestLooper;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Map;
+
+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 java.util.Map;
+
 /** Unit tests for android.net.lowpan.LowpanInterface. */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
diff --git a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java b/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java
index 3dd7504..998e8a5 100644
--- a/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java
+++ b/lowpan/tests/src/android/net/lowpan/LowpanManagerTest.java
@@ -26,8 +26,10 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.test.TestLooper;
-import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 5cb8fb8..30907a5 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -33,7 +33,10 @@
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiUtils;
+import android.hardware.hdmi.HdmiUtils.HdmiAddressRelativePosition;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -49,7 +52,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Retention;
@@ -145,6 +147,8 @@
     // Attributes specific to HDMI
     private final HdmiDeviceInfo mHdmiDeviceInfo;
     private final boolean mIsConnectedToHdmiSwitch;
+    @HdmiAddressRelativePosition
+    private final int mHdmiConnectionRelativePosition;
     private final String mParentId;
 
     private final Bundle mExtras;
@@ -260,7 +264,9 @@
     private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
             CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
             String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
-            boolean isConnectedToHdmiSwitch, String parentId, Bundle extras) {
+            boolean isConnectedToHdmiSwitch,
+            @HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId,
+            Bundle extras) {
         mService = service;
         mId = id;
         mType = type;
@@ -275,6 +281,7 @@
         mTunerCount = tunerCount;
         mHdmiDeviceInfo = hdmiDeviceInfo;
         mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
+        mHdmiConnectionRelativePosition = hdmiConnectionRelativePosition;
         mParentId = parentId;
         mExtras = extras;
     }
@@ -419,6 +426,7 @@
     /**
      * Returns {@code true}, if a CEC device for this TV input is connected to an HDMI switch, i.e.,
      * the device isn't directly connected to a HDMI port.
+     * TODO(b/110094868): add @Deprecated for Q
      * @hide
      */
     @SystemApi
@@ -427,6 +435,16 @@
     }
 
     /**
+     * Returns the relative position of this HDMI input.
+     * TODO(b/110094868): unhide for Q
+     * @hide
+     */
+    @HdmiAddressRelativePosition
+    public int getHdmiConnectionRelativePosition() {
+        return mHdmiConnectionRelativePosition;
+    }
+
+    /**
      * Checks if this TV input is marked hidden by the user in the settings.
      *
      * @param context Supplies a {@link Context} used to check if this TV input is hidden.
@@ -555,6 +573,7 @@
                 && mTunerCount == obj.mTunerCount
                 && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
                 && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
+                && mHdmiConnectionRelativePosition == obj.mHdmiConnectionRelativePosition
                 && TextUtils.equals(mParentId, obj.mParentId)
                 && Objects.equals(mExtras, obj.mExtras);
     }
@@ -589,6 +608,7 @@
         dest.writeInt(mTunerCount);
         dest.writeParcelable(mHdmiDeviceInfo, flags);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
+        dest.writeInt(mHdmiConnectionRelativePosition);
         dest.writeString(mParentId);
         dest.writeBundle(mExtras);
     }
@@ -630,6 +650,7 @@
         mTunerCount = in.readInt();
         mHdmiDeviceInfo = in.readParcelable(null);
         mIsConnectedToHdmiSwitch = in.readByte() == 1;
+        mHdmiConnectionRelativePosition = in.readInt();
         mParentId = in.readString();
         mExtras = in.readBundle();
     }
@@ -883,12 +904,17 @@
             int type;
             boolean isHardwareInput = false;
             boolean isConnectedToHdmiSwitch = false;
+            @HdmiAddressRelativePosition
+            int hdmiConnectionRelativePosition = HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN;
 
             if (mHdmiDeviceInfo != null) {
                 id = generateInputId(componentName, mHdmiDeviceInfo);
                 type = TYPE_HDMI;
                 isHardwareInput = true;
-                isConnectedToHdmiSwitch = (mHdmiDeviceInfo.getPhysicalAddress() & 0x0FFF) != 0;
+                hdmiConnectionRelativePosition = getRelativePosition(mContext, mHdmiDeviceInfo);
+                isConnectedToHdmiSwitch =
+                        hdmiConnectionRelativePosition
+                                != HdmiUtils.HDMI_RELATIVE_POSITION_DIRECTLY_BELOW;
             } else if (mTvInputHardwareInfo != null) {
                 id = generateInputId(componentName, mTvInputHardwareInfo);
                 type = sHardwareTypeToTvInputType.get(mTvInputHardwareInfo.getType(), TYPE_TUNER);
@@ -901,7 +927,8 @@
             return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
                     mIcon, mIconStandby, mIconDisconnected, mSetupActivity,
                     mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
-                    mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
+                    mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition,
+                    mParentId, mExtras);
         }
 
         private static String generateInputId(ComponentName name) {
@@ -923,6 +950,16 @@
                     + tvInputHardwareInfo.getDeviceId();
         }
 
+        private static int getRelativePosition(Context context, HdmiDeviceInfo info) {
+            HdmiControlManager hcm =
+                    (HdmiControlManager) context.getSystemService(Context.HDMI_CONTROL_SERVICE);
+            if (hcm == null) {
+                return HdmiUtils.HDMI_RELATIVE_POSITION_UNKNOWN;
+            }
+            return HdmiUtils.getHdmiAddressRelativePosition(
+                    info.getPhysicalAddress(), hcm.getPhysicalAddress());
+        }
+
         private void parseServiceMetadata(int inputType) {
             ServiceInfo si = mResolveInfo.serviceInfo;
             PackageManager pm = mContext.getPackageManager();
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 73d4c45..7c1af4a 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -56,6 +56,7 @@
 
     shared_libs: [
         "liblog",
+        "libhidlbase",
         "libcutils",
         "libandroidfw",
         "libinput",
@@ -70,6 +71,8 @@
         "libnetd_client",
         "libhwui",
         "libxml2",
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore-utils",
     ],
 
     static_libs: [
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 8be8eda..8b45af0 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -172,6 +172,7 @@
     ASensorEventQueue_hasEvents;
     ASensorEventQueue_registerSensor; # introduced=26
     ASensorEventQueue_setEventRate;
+    ASensorEventQueue_requestAdditionalInfoEvents; # introduced=29
     ASensorManager_configureDirectReport; # introduced=26
     ASensorManager_createEventQueue;
     ASensorManager_createHardwareBufferDirectChannel; # introduced=26
@@ -185,6 +186,7 @@
     ASensorManager_getSensorList;
     ASensor_getFifoMaxEventCount; # introduced=21
     ASensor_getFifoReservedEventCount; # introduced=21
+    ASensor_getHandle; # introduced=29
     ASensor_getHighestDirectReportRateLevel; # introduced=26
     ASensor_getMinDelay;
     ASensor_getName;
@@ -207,7 +209,7 @@
     AStorageManager_unmountObb;
     ASurfaceControl_create; # introduced=29
     ASurfaceControl_createFromWindow; # introduced=29
-    ASurfaceControl_destroy; # introduced=29
+    ASurfaceControl_release; # introduced=29
     ASurfaceTexture_acquireANativeWindow; # introduced=28
     ASurfaceTexture_attachToGLContext; # introduced=28
     ASurfaceTexture_detachFromGLContext; # introduced=28
@@ -216,13 +218,24 @@
     ASurfaceTexture_getTransformMatrix; # introduced=28
     ASurfaceTexture_release; # introduced=28
     ASurfaceTexture_updateTexImage; # introduced=28
+    ASurfaceTransactionStats_getAcquireTime; # introduced=29
+    ASurfaceTransactionStats_getASurfaceControls; # introduced=29
+    ASurfaceTransactionStats_getLatchTime; # introduced=29
+    ASurfaceTransactionStats_getPresentFenceFd; # introduced=29
+    ASurfaceTransactionStats_getPreviousReleaseFenceFd; # introduced=29
+    ASurfaceTransactionStats_releaseASurfaceControls; # introduced=29
     ASurfaceTransaction_apply; # introduced=29
     ASurfaceTransaction_create; # introduced=29
     ASurfaceTransaction_delete; # introduced=29
+    ASurfaceTransaction_reparent; # introduced=29
     ASurfaceTransaction_setBuffer; # introduced=29
+    ASurfaceTransaction_setBufferAlpha; # introduced=29
     ASurfaceTransaction_setBufferTransparency; # introduced=29
     ASurfaceTransaction_setDamageRegion; # introduced=29
+    ASurfaceTransaction_setDesiredPresentTime; # introduced=29
     ASurfaceTransaction_setGeometry; # introduced=29
+    ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29
+    ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29
     ASurfaceTransaction_setOnComplete; # introduced=29
     ASurfaceTransaction_setVisibility; # introduced=29
     ASurfaceTransaction_setZOrder; # introduced=29
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index c3b2e25..63082fd 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -115,6 +115,7 @@
     if (queue != 0) {
         ALooper_addFd(looper, queue->getFd(), ident, ALOOPER_EVENT_INPUT, callback, data);
         queue->looper = looper;
+        queue->requestAdditionalInfo = false;
         queue->incStrong(manager);
     }
     return static_cast<ASensorEventQueue*>(queue.get());
@@ -274,11 +275,19 @@
         return android::BAD_VALUE;
     }
 
-    ssize_t actual = static_cast<SensorEventQueue*>(queue)->read(events, count);
+    SensorEventQueue* sensorQueue = static_cast<SensorEventQueue*>(queue);
+    ssize_t actual = sensorQueue->read(events, count);
     if (actual > 0) {
-        static_cast<SensorEventQueue*>(queue)->sendAck(events, actual);
+        sensorQueue->sendAck(events, actual);
     }
-    return actual;
+
+    return sensorQueue->filterEvents(events, actual);
+}
+
+int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) {
+    RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE);
+    queue->requestAdditionalInfo = enable;
+    return android::OK;
 }
 
 /*****************************************************************************/
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index ead5b0b..f0100a9 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -14,14 +14,26 @@
  * limitations under the License.
  */
 
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <android/native_window.h>
 #include <android/surface_control.h>
 
+#include <configstore/Utils.h>
+
+#include <gui/HdrMetadata.h>
+#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceControl.h>
 
+#include <ui/HdrCapabilities.h>
+
+#include <utils/Timers.h>
+
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
 using namespace android;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
 
 using Transaction = SurfaceComposerClient::Transaction;
 
@@ -95,10 +107,9 @@
     return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
 }
 
-void ASurfaceControl_destroy(ASurfaceControl* aSurfaceControl) {
+void ASurfaceControl_release(ASurfaceControl* aSurfaceControl) {
     sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
 
-    Transaction().reparent(surfaceControl, nullptr).apply();
     SurfaceControl_release(surfaceControl.get());
 }
 
@@ -120,6 +131,86 @@
     transaction->apply();
 }
 
+typedef struct ASurfaceControlStats {
+    int64_t acquireTime;
+    sp<Fence> previousReleaseFence;
+} ASurfaceControlStats;
+
+struct ASurfaceTransactionStats {
+    std::unordered_map<ASurfaceControl*, ASurfaceControlStats> aSurfaceControlStats;
+    int64_t latchTime;
+    sp<Fence> presentFence;
+};
+
+int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* aSurfaceTransactionStats) {
+    CHECK_NOT_NULL(aSurfaceTransactionStats);
+    return aSurfaceTransactionStats->latchTime;
+}
+
+int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* aSurfaceTransactionStats) {
+    CHECK_NOT_NULL(aSurfaceTransactionStats);
+    auto& presentFence = aSurfaceTransactionStats->presentFence;
+    return (presentFence) ? presentFence->dup() : -1;
+}
+
+void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* aSurfaceTransactionStats,
+                                                  ASurfaceControl*** outASurfaceControls,
+                                                  size_t* outASurfaceControlsSize) {
+    CHECK_NOT_NULL(aSurfaceTransactionStats);
+    CHECK_NOT_NULL(outASurfaceControls);
+    CHECK_NOT_NULL(outASurfaceControlsSize);
+
+    size_t size = aSurfaceTransactionStats->aSurfaceControlStats.size();
+
+    SurfaceControl** surfaceControls = new SurfaceControl*[size];
+    ASurfaceControl** aSurfaceControls = reinterpret_cast<ASurfaceControl**>(surfaceControls);
+
+    size_t i = 0;
+    for (auto& [aSurfaceControl, aSurfaceControlStats] : aSurfaceTransactionStats->aSurfaceControlStats) {
+        aSurfaceControls[i] = aSurfaceControl;
+        i++;
+    }
+
+    *outASurfaceControls = aSurfaceControls;
+    *outASurfaceControlsSize = size;
+}
+
+int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* aSurfaceTransactionStats,
+                                                ASurfaceControl* aSurfaceControl) {
+    CHECK_NOT_NULL(aSurfaceTransactionStats);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    const auto& aSurfaceControlStats =
+            aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl);
+    LOG_ALWAYS_FATAL_IF(
+            aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(),
+            "ASurfaceControl not found");
+
+    return aSurfaceControlStats->second.acquireTime;
+}
+
+int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
+            ASurfaceTransactionStats* aSurfaceTransactionStats, ASurfaceControl* aSurfaceControl) {
+    CHECK_NOT_NULL(aSurfaceTransactionStats);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    const auto& aSurfaceControlStats =
+            aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl);
+    LOG_ALWAYS_FATAL_IF(
+            aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(),
+            "ASurfaceControl not found");
+
+    auto& previousReleaseFence = aSurfaceControlStats->second.previousReleaseFence;
+    return (previousReleaseFence) ? previousReleaseFence->dup() : -1;
+}
+
+void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** aSurfaceControls) {
+    CHECK_NOT_NULL(aSurfaceControls);
+
+    SurfaceControl** surfaceControls = reinterpret_cast<SurfaceControl**>(aSurfaceControls);
+    delete[] surfaceControls;
+}
+
 void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context,
                                        ASurfaceTransaction_OnComplete func) {
     CHECK_NOT_NULL(aSurfaceTransaction);
@@ -127,9 +218,23 @@
     CHECK_NOT_NULL(func);
 
     TransactionCompletedCallbackTakesContext callback = [func](void* callback_context,
-                                                               const TransactionStats& stats) {
-        int fence = (stats.presentFence) ? stats.presentFence->dup() : -1;
-        (*func)(callback_context, fence);
+                                                               nsecs_t latchTime,
+                                                               const sp<Fence>& presentFence,
+                                                               const std::vector<SurfaceControlStats>& surfaceControlStats) {
+        ASurfaceTransactionStats aSurfaceTransactionStats;
+
+        aSurfaceTransactionStats.latchTime = latchTime;
+        aSurfaceTransactionStats.presentFence = presentFence;
+
+        auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats;
+
+        for (const auto& [surfaceControl, acquireTime, previousReleaseFence] : surfaceControlStats) {
+            ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
+            aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime;
+            aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence;
+        }
+
+        (*func)(callback_context, &aSurfaceTransactionStats);
     };
 
     Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
@@ -137,7 +242,23 @@
     transaction->addTransactionCompletedCallback(callback, context);
 }
 
-void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+void ASurfaceTransaction_reparent(ASurfaceTransaction* aSurfaceTransaction,
+                                  ASurfaceControl* aSurfaceControl,
+                                  ASurfaceControl* newParentASurfaceControl) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    sp<SurfaceControl> newParentSurfaceControl = ASurfaceControl_to_SurfaceControl(
+            newParentASurfaceControl);
+    sp<IBinder> newParentHandle = (newParentSurfaceControl)? newParentSurfaceControl->getHandle() : nullptr;
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->reparent(surfaceControl, newParentHandle);
+}
+
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
+                                       ASurfaceControl* aSurfaceControl,
                                        int8_t visibility) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
@@ -157,7 +278,8 @@
     }
 }
 
-void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction,
+                                   ASurfaceControl* aSurfaceControl,
                                    int32_t z_order) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
@@ -168,8 +290,9 @@
     transaction->setLayer(surfaceControl, z_order);
 }
 
-void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
-                                   AHardwareBuffer* buffer, int fence_fd) {
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction,
+                                   ASurfaceControl* aSurfaceControl,
+                                   AHardwareBuffer* buffer, int acquire_fence_fd) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
 
@@ -179,8 +302,8 @@
     sp<GraphicBuffer> graphic_buffer(reinterpret_cast<GraphicBuffer*>(buffer));
 
     transaction->setBuffer(surfaceControl, graphic_buffer);
-    if (fence_fd != -1) {
-        sp<Fence> fence = new Fence(fence_fd);
+    if (acquire_fence_fd != -1) {
+        sp<Fence> fence = new Fence(acquire_fence_fd);
         transaction->setAcquireFence(surfaceControl, fence);
     }
 }
@@ -215,7 +338,8 @@
     transaction->setFlags(surfaceControl, flags, layer_state_t::eLayerOpaque);
 }
 
-void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl,
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction,
+                                         ASurfaceControl* aSurfaceControl,
                                          const ARect rects[], uint32_t count) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
@@ -230,3 +354,80 @@
 
     transaction->setSurfaceDamageRegion(surfaceControl, region);
 }
+
+void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* aSurfaceTransaction,
+                                         int64_t desiredPresentTime) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->setDesiredPresentTime(static_cast<nsecs_t>(desiredPresentTime));
+}
+
+void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* aSurfaceTransaction,
+                                         ASurfaceControl* aSurfaceControl,
+                                         float alpha) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    LOG_ALWAYS_FATAL_IF(alpha < 0.0 || alpha > 1.0, "invalid alpha");
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    transaction->setAlpha(surfaceControl, alpha);
+}
+
+void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction,
+                                                  ASurfaceControl* aSurfaceControl,
+                                                  struct AHdrMetadata_smpte2086* metadata) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    HdrMetadata hdrMetadata;
+
+    if (metadata) {
+        hdrMetadata.smpte2086.displayPrimaryRed.x = metadata->displayPrimaryRed.x;
+        hdrMetadata.smpte2086.displayPrimaryRed.y = metadata->displayPrimaryRed.y;
+        hdrMetadata.smpte2086.displayPrimaryGreen.x = metadata->displayPrimaryGreen.x;
+        hdrMetadata.smpte2086.displayPrimaryGreen.y = metadata->displayPrimaryGreen.y;
+        hdrMetadata.smpte2086.displayPrimaryBlue.x = metadata->displayPrimaryBlue.x;
+        hdrMetadata.smpte2086.displayPrimaryBlue.y = metadata->displayPrimaryBlue.y;
+        hdrMetadata.smpte2086.whitePoint.x = metadata->whitePoint.x;
+        hdrMetadata.smpte2086.whitePoint.y = metadata->whitePoint.y;
+        hdrMetadata.smpte2086.minLuminance = metadata->minLuminance;
+        hdrMetadata.smpte2086.maxLuminance = metadata->maxLuminance;
+
+        hdrMetadata.validTypes |= HdrMetadata::SMPTE2086;
+    } else {
+        hdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086;
+    }
+
+    transaction->setHdrMetadata(surfaceControl, hdrMetadata);
+}
+
+void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* aSurfaceTransaction,
+                                                 ASurfaceControl* aSurfaceControl,
+                                                 struct AHdrMetadata_cta861_3* metadata) {
+    CHECK_NOT_NULL(aSurfaceTransaction);
+    CHECK_NOT_NULL(aSurfaceControl);
+
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+
+    HdrMetadata hdrMetadata;
+
+    if (metadata) {
+        hdrMetadata.cta8613.maxContentLightLevel = metadata->maxContentLightLevel;
+        hdrMetadata.cta8613.maxFrameAverageLightLevel = metadata->maxFrameAverageLightLevel;
+
+        hdrMetadata.validTypes |= HdrMetadata::CTA861_3;
+    } else {
+        hdrMetadata.validTypes &= ~HdrMetadata::CTA861_3;
+    }
+
+    transaction->setHdrMetadata(surfaceControl, hdrMetadata);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 27dc628..9b12a31 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -622,7 +622,7 @@
                     .append(KEY_PREFIX_FQDN)
                     .append(config.FQDN).toString();
         } else {
-            return getKey(config.SSID, config.BSSID, getSecurity(config));
+            return getKey(removeDoubleQuotes(config.SSID), config.BSSID, getSecurity(config));
         }
     }
 
@@ -1555,7 +1555,7 @@
                     mOsuFailure = mContext.getString(
                             R.string.osu_failure_provisioning_not_available);
                     break;
-                case OSU_FAILURE_INVALID_SERVER_URL:
+                case OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU:
                     mOsuFailure = mContext.getString(R.string.osu_failure_invalid_server_url);
                     break;
                 case OSU_FAILURE_UNEXPECTED_COMMAND_TYPE:
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 98f0cbe..f2be2e7 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -458,6 +458,11 @@
          heads-up notifications.  -->
     <bool name="config_smart_replies_in_notifications_show_in_heads_up">true</bool>
 
+    <!-- Smart replies in notifications: Minimum number of system generated smart replies that
+         should be shown in a notification. If we cannot show at least this many replies we instead
+         show none. -->
+    <integer name="config_smart_replies_in_notifications_min_num_system_generated_replies">0</integer>
+
     <!-- Screenshot editing default activity.  Must handle ACTION_EDIT image/png intents.
          Blank sends the user to the Chooser first.
          This name is in the ComponentName flattened format (package/class)  -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 1aff394..7218acf 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,15 +1,9 @@
 package com.android.keyguard;
 
-import android.content.ContentResolver;
 import android.content.Context;
-import android.database.ContentObserver;
 import android.graphics.Paint;
 import android.graphics.Paint.Style;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.Settings;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -18,29 +12,19 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.keyguard.clock.BubbleClockController;
-import com.android.keyguard.clock.StretchAnalogClockController;
-import com.android.keyguard.clock.TypeClockController;
+import com.android.keyguard.clock.ClockManager;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionController.Extension;
 
-import java.util.Objects;
 import java.util.TimeZone;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
 
 /**
  * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
  */
 public class KeyguardClockSwitch extends RelativeLayout {
 
-    private LayoutInflater mLayoutInflater;
-
-    private final ContentResolver mContentResolver;
     /**
      * Optional/alternative clock injected via plugin.
      */
@@ -63,14 +47,6 @@
      */
     private View mKeyguardStatusArea;
     /**
-     * Used to select between plugin or default implementations of ClockPlugin interface.
-     */
-    private Extension<ClockPlugin> mClockExtension;
-    /**
-     * Consumer that accepts the a new ClockPlugin implementation when the Extension reloads.
-     */
-    private final Consumer<ClockPlugin> mClockPluginConsumer = plugin -> setClockPlugin(plugin);
-    /**
      * Maintain state so that a newly connected plugin can be initialized.
      */
     private float mDarkAmount;
@@ -94,16 +70,7 @@
                 }
     };
 
-    private final ContentObserver mContentObserver =
-            new ContentObserver(new Handler(Looper.getMainLooper())) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    super.onChange(selfChange);
-                    if (mClockExtension != null) {
-                        mClockExtension.reload();
-                    }
-                }
-    };
+    private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
 
     public KeyguardClockSwitch(Context context) {
         this(context, null);
@@ -111,8 +78,6 @@
 
     public KeyguardClockSwitch(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mLayoutInflater = LayoutInflater.from(context);
-        mContentResolver = context.getContentResolver();
     }
 
     /**
@@ -133,45 +98,14 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mClockExtension = Dependency.get(ExtensionController.class).newExtension(ClockPlugin.class)
-                .withPlugin(ClockPlugin.class)
-                .withCallback(mClockPluginConsumer)
-                // Using withDefault even though this isn't the default as a workaround.
-                // ExtensionBulider doesn't provide the ability to supply a ClockPlugin
-                // instance based off of the value of a setting. Since multiple "default"
-                // can be provided, using a supplier that changes the settings value.
-                // A null return will cause Extension#reload to look at the next "default"
-                // supplier.
-                .withDefault(
-                        new SettingsGattedSupplier(
-                                mContentResolver,
-                                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)))
-                .withDefault(
-                        new SettingsGattedSupplier(
-                                mContentResolver,
-                                Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
-                                TypeClockController.class.getName(),
-                                () -> TypeClockController.build(mLayoutInflater)))
-                .build();
-        mContentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
-                false, mContentObserver);
+        Dependency.get(ClockManager.class).addOnClockChangedListener(mClockChangedListener);
         Dependency.get(StatusBarStateController.class).addCallback(mStateListener);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        mClockExtension.destroy();
-        mContentResolver.unregisterContentObserver(mContentObserver);
+        Dependency.get(ClockManager.class).removeOnClockChangedListener(mClockChangedListener);
         Dependency.get(StatusBarStateController.class).removeCallback(mStateListener);
     }
 
@@ -313,52 +247,12 @@
     }
 
     @VisibleForTesting (otherwise = VisibleForTesting.NONE)
-    Consumer<ClockPlugin> getClockPluginConsumer() {
-        return mClockPluginConsumer;
+    ClockManager.ClockChangedListener getClockChangedListener() {
+        return mClockChangedListener;
     }
 
     @VisibleForTesting (otherwise = VisibleForTesting.NONE)
     StatusBarStateController.StateListener getStateListener() {
         return mStateListener;
     }
-
-    /**
-     * Supplier that only gets an instance when a settings value matches expected value.
-     */
-    private static class SettingsGattedSupplier implements Supplier<ClockPlugin> {
-
-        private final ContentResolver mContentResolver;
-        private final String mKey;
-        private final String mValue;
-        private final Supplier<ClockPlugin> mSupplier;
-
-        /**
-         * Constructs a supplier that changes secure setting key against value.
-         *
-         * @param contentResolver Used to look up settings value.
-         * @param key Settings key.
-         * @param value If the setting matches this values that get supplies a ClockPlugin
-         *        instance.
-         * @param supplier Supplier of ClockPlugin instance, only used if the setting
-         *        matches value.
-         */
-        SettingsGattedSupplier(ContentResolver contentResolver, String key, String value,
-                Supplier<ClockPlugin> supplier) {
-            mContentResolver = contentResolver;
-            mKey = key;
-            mValue = value;
-            mSupplier = supplier;
-        }
-
-        /**
-         * Returns null if the settings value doesn't match the expected value.
-         *
-         * A null return causes Extension#reload to skip this supplier and move to the next.
-         */
-        @Override
-        public ClockPlugin get() {
-            final String currentValue = Settings.Secure.getString(mContentResolver, mKey);
-            return Objects.equals(currentValue, mValue) ? mSupplier.get() : null;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
new file mode 100644
index 0000000..3217ca6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -0,0 +1,202 @@
+/*
+ * 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.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Manages custom clock faces.
+ */
+@Singleton
+public final class ClockManager {
+
+    private final LayoutInflater mLayoutInflater;
+    private final ContentResolver mContentResolver;
+
+    /**
+     * Observe settings changes to know when to switch the clock face.
+     */
+    private final ContentObserver mContentObserver =
+            new ContentObserver(new Handler(Looper.getMainLooper())) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    super.onChange(selfChange);
+                    if (mClockExtension != null) {
+                        mClockExtension.reload();
+                    }
+                }
+            };
+
+    private final ExtensionController mExtensionController;
+    /**
+     * Used to select between plugin or default implementations of ClockPlugin interface.
+     */
+    private Extension<ClockPlugin> mClockExtension;
+    /**
+     * Consumer that accepts the a new ClockPlugin implementation when the Extension reloads.
+     */
+    private final Consumer<ClockPlugin> mClockPluginConsumer = this::setClockPlugin;
+
+    private final List<ClockChangedListener> mListeners = new ArrayList<>();
+
+    @Inject
+    public ClockManager(Context context, ExtensionController extensionController) {
+        mExtensionController = extensionController;
+        mLayoutInflater = LayoutInflater.from(context);
+        mContentResolver = context.getContentResolver();
+    }
+
+    /**
+     * Add listener to be notified when clock implementation should change.
+     */
+    public void addOnClockChangedListener(ClockChangedListener listener) {
+        if (mListeners.isEmpty()) {
+            register();
+        }
+        mListeners.add(listener);
+        if (mClockExtension != null) {
+            mClockExtension.reload();
+        }
+    }
+
+    /**
+     * Remove listener added with {@link addOnClockChangedListener}.
+     */
+    public void removeOnClockChangedListener(ClockChangedListener listener) {
+        mListeners.remove(listener);
+        if (mListeners.isEmpty()) {
+            unregister();
+        }
+    }
+
+    private void setClockPlugin(ClockPlugin plugin) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            // It probably doesn't make sense to supply the same plugin instances to multiple
+            // listeners. This should be fine for now since there is only a single listener.
+            mListeners.get(i).onClockChanged(plugin);
+        }
+    }
+
+    private void register() {
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
+                false, mContentObserver);
+        mClockExtension = mExtensionController.newExtension(ClockPlugin.class)
+            .withPlugin(ClockPlugin.class)
+            .withCallback(mClockPluginConsumer)
+            // Using withDefault even though this isn't the default as a workaround.
+            // ExtensionBuilder doesn't provide the ability to supply a ClockPlugin
+            // instance based off of the value of a setting. Since multiple "default"
+            // can be provided, using a supplier that changes the settings value.
+            // A null return will cause Extension#reload to look at the next "default"
+            // supplier.
+            .withDefault(
+                    new SettingsGattedSupplier(
+                        mContentResolver,
+                        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)))
+            .withDefault(
+                    new SettingsGattedSupplier(
+                        mContentResolver,
+                        Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+                        TypeClockController.class.getName(),
+                            () -> TypeClockController.build(mLayoutInflater)))
+            .build();
+    }
+
+    private void unregister() {
+        mContentResolver.unregisterContentObserver(mContentObserver);
+        mClockExtension.destroy();
+    }
+
+    /**
+     * Listener for events that should cause the custom clock face to change.
+     */
+    public interface ClockChangedListener {
+        /**
+         * Called when custom clock should change.
+         *
+         * @param clock Custom clock face to use. A null value indicates the default clock face.
+         */
+        void onClockChanged(ClockPlugin clock);
+    }
+
+    /**
+     * Supplier that only gets an instance when a settings value matches expected value.
+     */
+    private static class SettingsGattedSupplier implements Supplier<ClockPlugin> {
+
+        private final ContentResolver mContentResolver;
+        private final String mKey;
+        private final String mValue;
+        private final Supplier<ClockPlugin> mSupplier;
+
+        /**
+         * Constructs a supplier that changes secure setting key against value.
+         *
+         * @param contentResolver Used to look up settings value.
+         * @param key Settings key.
+         * @param value If the setting matches this values that get supplies a ClockPlugin
+         *        instance.
+         * @param supplier Supplier of ClockPlugin instance, only used if the setting
+         *        matches value.
+         */
+        SettingsGattedSupplier(ContentResolver contentResolver, String key, String value,
+                Supplier<ClockPlugin> supplier) {
+            mContentResolver = contentResolver;
+            mKey = key;
+            mValue = value;
+            mSupplier = supplier;
+        }
+
+        /**
+         * Returns null if the settings value doesn't match the expected value.
+         *
+         * A null return causes Extension#reload to skip this supplier and move to the next.
+         */
+        @Override
+        public ClockPlugin get() {
+            final String currentValue = Settings.Secure.getString(mContentResolver, mKey);
+            return Objects.equals(currentValue, mValue) ? mSupplier.get() : null;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index ec6ecc6..d99f234 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -29,6 +29,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.Preconditions;
+import com.android.keyguard.clock.ClockManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.systemui.appops.AppOpsController;
 import com.android.systemui.assist.AssistManager;
@@ -283,6 +284,7 @@
     @Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
     @Nullable
     @Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
+    @Inject Lazy<ClockManager> mClockManager;
 
     @Inject
     public Dependency() {
@@ -449,6 +451,7 @@
         mProviders.put(NotificationAlertingManager.class, mNotificationAlertingManager::get);
         mProviders.put(ForegroundServiceNotificationListener.class,
                 mForegroundServiceNotificationListener::get);
+        mProviders.put(ClockManager.class, mClockManager::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 957d772..a457dee 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -267,8 +267,9 @@
             BubbleView bubble = (BubbleView) mInflater.inflate(
                     R.layout.bubble_view, mStackView, false /* attachToRoot */);
             bubble.setNotif(notif);
-            if (shouldUseActivityView(mContext)) {
-                bubble.setAppOverlayIntent(getAppOverlayIntent(notif));
+            PendingIntent bubbleIntent = getValidBubbleIntent(notif);
+            if (shouldUseActivityView(mContext) || bubbleIntent != null) {
+                bubble.setBubbleIntent(getValidBubbleIntent(notif));
             }
             mBubbles.put(bubble.getKey(), bubble);
             mStackView.addBubble(bubble);
@@ -282,7 +283,7 @@
     }
 
     @Nullable
-    private PendingIntent getAppOverlayIntent(NotificationEntry notif) {
+    private PendingIntent getValidBubbleIntent(NotificationEntry notif) {
         Notification notification = notif.notification.getNotification();
         if (canLaunchInActivityView(notification.getBubbleMetadata() != null
                 ? notification.getBubbleMetadata().getIntent() : null)) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 9a11b96..dcd121b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -38,9 +38,11 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.OvershootInterpolator;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 
 import androidx.annotation.Nullable;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -226,6 +228,19 @@
     }
 
     /**
+     * Sets the entry that should be expanded and expands if needed.
+     */
+    @VisibleForTesting
+    public void setExpandedBubble(NotificationEntry entry) {
+        for (int i = 0; i < mBubbleContainer.getChildCount(); i++) {
+            BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i);
+            if (entry.equals(bv.getEntry())) {
+                setExpandedBubble(bv);
+            }
+        }
+    }
+
+    /**
      * Adds a bubble to the top of the stack.
      *
      * @param bubbleView the view to add to the stack.
@@ -456,7 +471,8 @@
         if (mExpandedBubble.hasAppOverlayIntent()) {
             // Bubble with activity view expanded state
             ActivityView expandedView = mExpandedBubble.getActivityView();
-            expandedView.setLayoutParams(new ViewGroup.LayoutParams(
+            // XXX: gets added to linear layout
+            expandedView.setLayoutParams(new LinearLayout.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT, mExpandedBubbleHeight));
 
             final PendingIntent intent = mExpandedBubble.getAppOverlayIntent();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 91893ef..7b6e79b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -298,7 +298,7 @@
 
     }
 
-    public void setAppOverlayIntent(PendingIntent intent) {
+    public void setBubbleIntent(PendingIntent intent) {
         mAppOverlayIntent = intent;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
index fa5a114..d332f59 100644
--- a/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
+++ b/packages/SystemUI/src/com/android/systemui/dock/DockManager.java
@@ -48,6 +48,11 @@
      */
     void removeListener(DockEventListener callback);
 
+    /**
+    * Returns true if the device is in docking state.
+    */
+    boolean isDocked();
+
     /** Callback for receiving dock events */
     interface DockEventListener {
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
index 9fc2234..5353ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeDockHandler.java
@@ -22,7 +22,6 @@
 import android.util.Log;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.doze.DozeMachine.State;
 
@@ -46,12 +45,12 @@
     private int mDockState = DockManager.STATE_NONE;
 
     public DozeDockHandler(Context context, DozeMachine machine, DozeHost dozeHost,
-            AmbientDisplayConfiguration config, Handler handler) {
+            AmbientDisplayConfiguration config, Handler handler, DockManager dockManager) {
         mMachine = machine;
         mDozeHost = dozeHost;
         mConfig = config;
         mHandler = handler;
-        mDockManager = SysUiServiceProvider.getComponent(context, DockManager.class);
+        mDockManager = dockManager;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 58ae555..e338a34 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -27,8 +27,10 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.AsyncSensorManager;
 import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -44,6 +46,7 @@
         Context context = dozeService;
         SensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
         AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
+        DockManager dockManager = SysUiServiceProvider.getComponent(context, DockManager.class);
 
         DozeHost host = getHost(dozeService);
         AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
@@ -63,13 +66,13 @@
                 new DozePauser(handler, machine, alarmManager, params.getPolicy()),
                 new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
                 createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
-                        handler, wakeLock, machine),
+                        handler, wakeLock, machine, dockManager),
                 createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
                 new DozeScreenState(wrappedService, handler, params, wakeLock),
                 createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
                         handler),
                 new DozeWallpaperState(context),
-                new DozeDockHandler(context, machine, host, config, handler)
+                new DozeDockHandler(context, machine, host, config, handler, dockManager)
         });
 
         return machine;
@@ -86,10 +89,11 @@
 
     private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
             DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
-            DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine) {
+            DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine,
+            DockManager dockManager) {
         boolean allowPulseTriggers = true;
         return new DozeTriggers(context, machine, host, alarmManager, config, params,
-                sensorManager, handler, wakeLock, allowPulseTriggers);
+                sensorManager, handler, wakeLock, allowPulseTriggers, dockManager);
     }
 
     private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 78374a0..562edd6 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -214,6 +214,15 @@
         mPickupSensor.setDisabled(disable);
     }
 
+    /** Ignore the setting value of only the sensors that require the touchscreen. */
+    public void ignoreTouchScreenSensorsSettingInterferingWithDocking(boolean ignore) {
+        for (TriggerSensor sensor : mSensors) {
+            if (sensor.mRequiresTouchscreen) {
+                sensor.ignoreSetting(ignore);
+            }
+        }
+    }
+
     /** Dump current state */
     public void dump(PrintWriter pw) {
         for (TriggerSensor s : mSensors) {
@@ -323,6 +332,7 @@
         protected boolean mRequested;
         protected boolean mRegistered;
         protected boolean mDisabled;
+        protected boolean mIgnoresSetting;
 
         public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason,
                 boolean reportsTouchCoordinates, boolean requiresTouchscreen) {
@@ -333,6 +343,13 @@
         public TriggerSensor(Sensor sensor, String setting, boolean settingDef,
                 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
                 boolean requiresTouchscreen) {
+            this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
+                    requiresTouchscreen, false /* ignoresSetting */);
+        }
+
+        private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
+                boolean configured, int pulseReason, boolean reportsTouchCoordinates,
+                boolean requiresTouchscreen, boolean ignoresSetting) {
             mSensor = sensor;
             mSetting = setting;
             mSettingDefault = settingDef;
@@ -340,6 +357,7 @@
             mPulseReason = pulseReason;
             mReportsTouchCoordinates = reportsTouchCoordinates;
             mRequiresTouchscreen = requiresTouchscreen;
+            mIgnoresSetting = ignoresSetting;
         }
 
         public void setListening(boolean listen) {
@@ -354,9 +372,16 @@
             updateListener();
         }
 
+        public void ignoreSetting(boolean ignored) {
+            if (mIgnoresSetting == ignored) return;
+            mIgnoresSetting = ignored;
+            updateListener();
+        }
+
         public void updateListener() {
             if (!mConfigured || mSensor == null) return;
-            if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
+            if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
+                    && !mRegistered) {
                 mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
                 if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered);
             } else if (mRegistered) {
@@ -382,6 +407,7 @@
                     .append(", mRequested=").append(mRequested)
                     .append(", mDisabled=").append(mDisabled)
                     .append(", mConfigured=").append(mConfigured)
+                    .append(", mIgnoresSetting=").append(mIgnoresSetting)
                     .append(", mSensor=").append(mSensor).append("}").toString();
         }
 
@@ -464,7 +490,8 @@
         public void updateListener() {
             if (!mConfigured) return;
             AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
-            if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
+            if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
+                    && !mRegistered) {
                 asyncSensorManager.registerPluginListener(mPluginSensor, mTriggerEventListener);
                 mRegistered = true;
                 if (DEBUG) Log.d(TAG, "registerPluginListener");
@@ -481,6 +508,7 @@
                     .append(", mRequested=").append(mRequested)
                     .append(", mDisabled=").append(mDisabled)
                     .append(", mConfigured=").append(mConfigured)
+                    .append(", mIgnoresSetting=").append(mIgnoresSetting)
                     .append(", mSensor=").append(mPluginSensor).append("}").toString();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index e2e448b..dc505b5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -33,8 +33,10 @@
 import android.text.format.Formatter;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.Preconditions;
+import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.wakelock.WakeLock;
@@ -71,6 +73,8 @@
     private final boolean mAllowPulseTriggers;
     private final UiModeManager mUiModeManager;
     private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
+    private final DockEventListener mDockEventListener = new DockEventListener();
+    private final DockManager mDockManager;
 
     private long mNotificationPulseTime;
     private boolean mPulsePending;
@@ -79,7 +83,7 @@
     public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
             AlarmManager alarmManager, AmbientDisplayConfiguration config,
             DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
-            WakeLock wakeLock, boolean allowPulseTriggers) {
+            WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager) {
         mContext = context;
         mMachine = machine;
         mDozeHost = dozeHost;
@@ -93,6 +97,7 @@
                 config, wakeLock, this::onSensor, this::onProximityFar,
                 dozeParameters.getPolicy());
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
+        mDockManager = dockManager;
     }
 
     private void onNotification() {
@@ -129,7 +134,8 @@
         }
     }
 
-    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
+    @VisibleForTesting
+    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;
@@ -159,7 +165,7 @@
                 } else {
                     mDozeHost.extendPulse();
                 }
-            }, sensorPerformedProxCheck, pulseReason);
+            }, sensorPerformedProxCheck || mDockManager.isDocked(), pulseReason);
         }
 
         if (isPickup) {
@@ -223,6 +229,7 @@
             case INITIALIZED:
                 mBroadcastReceiver.register(mContext);
                 mDozeHost.addCallback(mHostCallback);
+                mDockManager.addListener(mDockEventListener);
                 checkTriggersAtInit();
                 break;
             case DOZE:
@@ -248,6 +255,7 @@
             case FINISH:
                 mBroadcastReceiver.unregister(mContext);
                 mDozeHost.removeCallback(mHostCallback);
+                mDockManager.removeListener(mDockEventListener);
                 mDozeSensors.setListening(false);
                 mDozeSensors.setProxListening(false);
                 break;
@@ -423,6 +431,24 @@
         }
     }
 
+    private class DockEventListener implements DockManager.DockEventListener {
+        @Override
+        public void onEvent(int event) {
+            if (DEBUG) Log.d(TAG, "dock event = " + event);
+            switch (event) {
+                case DockManager.STATE_DOCKED:
+                case DockManager.STATE_DOCKED_HIDE:
+                    mDozeSensors.ignoreTouchScreenSensorsSettingInterferingWithDocking(true);
+                    break;
+                case DockManager.STATE_NONE:
+                    mDozeSensors.ignoreTouchScreenSensorsSettingInterferingWithDocking(false);
+                    break;
+                default:
+                    // no-op
+            }
+        }
+    }
+
     private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
         @Override
         public void onNotificationAlerted() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 5ba9b4b..76d394d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -32,6 +32,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.StatusBarStateController;
@@ -460,7 +461,9 @@
             mUiOffloadThread.submit(() -> {
                 try {
                     mBarService.onNotificationExpansionChanged(
-                            key, stateToBeLogged.mIsUserAction, stateToBeLogged.mIsExpanded);
+                            key, stateToBeLogged.mIsUserAction, stateToBeLogged.mIsExpanded,
+                            // TODO (b/120767764): fill in location
+                            ExpandableViewState.LOCATION_UNKNOWN /* notificationLocation */);
                 } catch (RemoteException e) {
                     Log.e(TAG, "Failed to call onNotificationExpansionChanged: ", e);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 2a11c26..d022808 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -97,10 +97,11 @@
         }
         return mClickableChildren
                 .stream()
-                .filter(v -> v.isAttachedToWindow())
+                .filter(View::isAttachedToWindow)
                 .map(v -> new Pair<>(distance(v, event), v))
                 .min(Comparator.comparingInt(f -> f.first))
-                .get().second;
+                .map(data -> data.second)
+                .orElse(null);
     }
 
     private int distance(View v, MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 88f9048..ffaa236 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -69,13 +69,13 @@
     private final WindowManager mWindowManager;
     private final IActivityManager mActivityManager;
     private final DozeParameters mDozeParameters;
+    private final WindowManager.LayoutParams mLpChanged;
+    private final boolean mKeyguardScreenRotation;
     private ViewGroup mStatusBarView;
     private WindowManager.LayoutParams mLp;
-    private WindowManager.LayoutParams mLpChanged;
     private boolean mHasTopUi;
     private boolean mHasTopUiChanged;
     private int mBarHeight;
-    private final boolean mKeyguardScreenRotation;
     private float mScreenBrightnessDoze;
     private final State mCurrentState = new State();
     private OtherwisedCollapsedListener mListener;
@@ -97,6 +97,7 @@
         mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
         mDozeParameters = dozeParameters;
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
+        mLpChanged = new WindowManager.LayoutParams();
         Dependency.get(StatusBarStateController.class).addCallback(
                 mStateListener, StatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
         Dependency.get(ConfigurationController.class).addCallback(this);
@@ -138,7 +139,6 @@
         mStatusBarView = statusBarView;
         mBarHeight = barHeight;
         mWindowManager.addView(mStatusBarView, mLp);
-        mLpChanged = new WindowManager.LayoutParams();
         mLpChanged.copyFrom(mLp);
         onThemeChanged();
     }
@@ -228,7 +228,9 @@
     private void applyHeight(State state) {
         boolean expanded = isExpanded(state);
         if (state.forcePluginOpen) {
-            mListener.setWouldOtherwiseCollapse(expanded);
+            if (mListener != null) {
+                mListener.setWouldOtherwiseCollapse(expanded);
+            }
             expanded = true;
         }
         if (expanded) {
@@ -247,7 +249,7 @@
 
     private void applyFitsSystemWindows(State state) {
         boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
-        if (mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) {
+        if (mStatusBarView != null && mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) {
             mStatusBarView.setFitsSystemWindows(fitsSystemWindows);
             mStatusBarView.requestApplyInsets();
         }
@@ -289,7 +291,7 @@
         applyBrightness(state);
         applyHasTopUi(state);
         applyNotTouchable(state);
-        if (mLp.copyFrom(mLpChanged) != 0) {
+        if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
             mWindowManager.updateViewLayout(mStatusBarView, mLp);
         }
         if (mHasTopUi != mHasTopUiChanged) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 3bd0d45..db04620 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -46,18 +46,21 @@
     private static final String KEY_EDIT_CHOICES_BEFORE_SENDING =
             "edit_choices_before_sending";
     private static final String KEY_SHOW_IN_HEADS_UP = "show_in_heads_up";
+    private static final String KEY_MIN_NUM_REPLIES = "min_num_system_generated_replies";
 
     private final boolean mDefaultEnabled;
     private final boolean mDefaultRequiresP;
     private final int mDefaultMaxSqueezeRemeasureAttempts;
     private final boolean mDefaultEditChoicesBeforeSending;
     private final boolean mDefaultShowInHeadsUp;
+    private final int mDefaultMinNumSystemGeneratedReplies;
 
     private boolean mEnabled;
     private boolean mRequiresTargetingP;
     private int mMaxSqueezeRemeasureAttempts;
     private boolean mEditChoicesBeforeSending;
     private boolean mShowInHeadsUp;
+    private int mMinNumSystemGeneratedReplies;
 
     private final Context mContext;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -78,6 +81,8 @@
                 R.bool.config_smart_replies_in_notifications_edit_choices_before_sending);
         mDefaultShowInHeadsUp = resources.getBoolean(
                 R.bool.config_smart_replies_in_notifications_show_in_heads_up);
+        mDefaultMinNumSystemGeneratedReplies = resources.getInteger(
+                R.integer.config_smart_replies_in_notifications_min_num_system_generated_replies);
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS),
@@ -105,6 +110,8 @@
             mEditChoicesBeforeSending = mParser.getBoolean(
                     KEY_EDIT_CHOICES_BEFORE_SENDING, mDefaultEditChoicesBeforeSending);
             mShowInHeadsUp = mParser.getBoolean(KEY_SHOW_IN_HEADS_UP, mDefaultShowInHeadsUp);
+            mMinNumSystemGeneratedReplies =
+                    mParser.getInt(KEY_MIN_NUM_REPLIES, mDefaultMinNumSystemGeneratedReplies);
         }
     }
 
@@ -155,4 +162,12 @@
     public boolean getShowInHeadsUp() {
         return mShowInHeadsUp;
     }
+
+    /**
+     * Returns the minimum number of system generated replies to show in a notification.
+     * If we cannot show at least this many system generated replies we should show none.
+     */
+    public int getMinNumSystemGeneratedReplies() {
+        return mMinNumSystemGeneratedReplies;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index d6eff94..c4f027f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -88,6 +88,12 @@
 
     private View mSmartReplyContainer;
 
+    /**
+     * Whether the smart replies in this view were generated by the notification assistant. If not
+     * they're provided by the app.
+     */
+    private boolean mSmartRepliesGeneratedByAssistant = false;
+
     @ColorInt
     private int mCurrentBackgroundColor;
     @ColorInt
@@ -202,6 +208,7 @@
                             getContext(), this, i, smartReplies, smartReplyController, entry);
                     addView(replyButton);
                 }
+                this.mSmartRepliesGeneratedByAssistant = smartReplies.fromAssistant;
             }
         }
         reallocateCandidateButtonQueueForSqueezing();
@@ -344,10 +351,11 @@
             mCandidateButtonQueueForSqueezing.clear();
         }
 
-        int measuredWidth = mPaddingLeft + mPaddingRight;
-        int maxChildHeight = 0;
+        SmartSuggestionMeasures accumulatedMeasures = new SmartSuggestionMeasures(
+                mPaddingLeft + mPaddingRight,
+                0 /* maxChildHeight */,
+                mSingleLineButtonPaddingHorizontal);
         int displayedChildCount = 0;
-        int buttonPaddingHorizontal = mSingleLineButtonPaddingHorizontal;
 
         // Set up a list of suggestions where actions come before replies. Note that the Buttons
         // themselves have already been added to the view hierarchy in an order such that Smart
@@ -360,11 +368,15 @@
         smartSuggestions.addAll(smartReplies);
         List<View> coveredSuggestions = new ArrayList<>();
 
+        // SmartSuggestionMeasures for all action buttons, this will be filled in when the first
+        // reply button is added.
+        SmartSuggestionMeasures actionsMeasures = null;
+
         for (View child : smartSuggestions) {
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
-            child.setPadding(buttonPaddingHorizontal, child.getPaddingTop(),
-                    buttonPaddingHorizontal, child.getPaddingBottom());
+            child.setPadding(accumulatedMeasures.mButtonPaddingHorizontal, child.getPaddingTop(),
+                    accumulatedMeasures.mButtonPaddingHorizontal, child.getPaddingBottom());
             child.measure(MEASURE_SPEC_ANY_LENGTH, heightMeasureSpec);
 
             coveredSuggestions.add(child);
@@ -380,45 +392,52 @@
             }
 
             // Remember the current measurements in case the current button doesn't fit in.
-            final int originalMaxChildHeight = maxChildHeight;
-            final int originalMeasuredWidth = measuredWidth;
-            final int originalButtonPaddingHorizontal = buttonPaddingHorizontal;
+            SmartSuggestionMeasures originalMeasures = accumulatedMeasures.clone();
+            if (actionsMeasures == null && lp.buttonType == SmartButtonType.REPLY) {
+                // We've added all actions (we go through actions first), now add their
+                // measurements.
+                actionsMeasures = accumulatedMeasures.clone();
+            }
 
             final int spacing = displayedChildCount == 0 ? 0 : mSpacing;
             final int childWidth = child.getMeasuredWidth();
             final int childHeight = child.getMeasuredHeight();
-            measuredWidth += spacing + childWidth;
-            maxChildHeight = Math.max(maxChildHeight, childHeight);
+            accumulatedMeasures.mMeasuredWidth += spacing + childWidth;
+            accumulatedMeasures.mMaxChildHeight =
+                    Math.max(accumulatedMeasures.mMaxChildHeight, childHeight);
 
             // Do we need to increase the number of lines in smart reply buttons to two?
             final boolean increaseToTwoLines =
-                    buttonPaddingHorizontal == mSingleLineButtonPaddingHorizontal
-                            && (lineCount == 2 || measuredWidth > targetWidth);
+                    (accumulatedMeasures.mButtonPaddingHorizontal
+                            == mSingleLineButtonPaddingHorizontal)
+                    && (lineCount == 2 || accumulatedMeasures.mMeasuredWidth > targetWidth);
             if (increaseToTwoLines) {
-                measuredWidth += (displayedChildCount + 1) * mSingleToDoubleLineButtonWidthIncrease;
-                buttonPaddingHorizontal = mDoubleLineButtonPaddingHorizontal;
+                accumulatedMeasures.mMeasuredWidth +=
+                        (displayedChildCount + 1) * mSingleToDoubleLineButtonWidthIncrease;
+                accumulatedMeasures.mButtonPaddingHorizontal =
+                        mDoubleLineButtonPaddingHorizontal;
             }
 
             // If the last button doesn't fit into the remaining width, try squeezing preceding
             // smart reply buttons.
-            if (measuredWidth > targetWidth) {
+            if (accumulatedMeasures.mMeasuredWidth > targetWidth) {
                 // Keep squeezing preceding and current smart reply buttons until they all fit.
-                while (measuredWidth > targetWidth
+                while (accumulatedMeasures.mMeasuredWidth > targetWidth
                         && !mCandidateButtonQueueForSqueezing.isEmpty()) {
                     final Button candidate = mCandidateButtonQueueForSqueezing.poll();
                     final int squeezeReduction = squeezeButton(candidate, heightMeasureSpec);
                     if (squeezeReduction != SQUEEZE_FAILED) {
-                        maxChildHeight = Math.max(maxChildHeight, candidate.getMeasuredHeight());
-                        measuredWidth -= squeezeReduction;
+                        accumulatedMeasures.mMaxChildHeight =
+                                Math.max(accumulatedMeasures.mMaxChildHeight,
+                                        candidate.getMeasuredHeight());
+                        accumulatedMeasures.mMeasuredWidth -= squeezeReduction;
                     }
                 }
 
                 // If the current button still doesn't fit after squeezing all buttons, undo the
                 // last squeezing round.
-                if (measuredWidth > targetWidth) {
-                    measuredWidth = originalMeasuredWidth;
-                    maxChildHeight = originalMaxChildHeight;
-                    buttonPaddingHorizontal = originalButtonPaddingHorizontal;
+                if (accumulatedMeasures.mMeasuredWidth > targetWidth) {
+                    accumulatedMeasures = originalMeasures;
 
                     // Mark all buttons from the last squeezing round as "failed to squeeze", so
                     // that they're re-measured without squeezing later.
@@ -440,16 +459,75 @@
             displayedChildCount++;
         }
 
+        if (mSmartRepliesGeneratedByAssistant) {
+            if (!gotEnoughSmartReplies(smartReplies)) {
+                // We don't have enough smart replies - hide all of them.
+                for (View smartReplyButton : smartReplies) {
+                    final LayoutParams lp = (LayoutParams) smartReplyButton.getLayoutParams();
+                    lp.show = false;
+                }
+                // Reset our measures back to when we had only added actions (before adding
+                // replies).
+                accumulatedMeasures = actionsMeasures;
+            }
+        }
+
         // We're done squeezing buttons, so we can clear the priority queue.
         mCandidateButtonQueueForSqueezing.clear();
 
         // Finally, we need to re-measure some buttons.
-        remeasureButtonsIfNecessary(buttonPaddingHorizontal, maxChildHeight);
+        remeasureButtonsIfNecessary(accumulatedMeasures.mButtonPaddingHorizontal,
+                                    accumulatedMeasures.mMaxChildHeight);
 
         setMeasuredDimension(
-                resolveSize(Math.max(getSuggestedMinimumWidth(), measuredWidth), widthMeasureSpec),
-                resolveSize(Math.max(getSuggestedMinimumHeight(),
-                        mPaddingTop + maxChildHeight + mPaddingBottom), heightMeasureSpec));
+                resolveSize(Math.max(getSuggestedMinimumWidth(),
+                                     accumulatedMeasures.mMeasuredWidth),
+                            widthMeasureSpec),
+                resolveSize(Math.max(getSuggestedMinimumHeight(), mPaddingTop
+                        + accumulatedMeasures.mMaxChildHeight + mPaddingBottom),
+                            heightMeasureSpec));
+    }
+
+    /**
+     * Fields we keep track of inside onMeasure() to correctly measure the SmartReplyView depending
+     * on which suggestions are added.
+     */
+    private static class SmartSuggestionMeasures {
+        int mMeasuredWidth = -1;
+        int mMaxChildHeight = -1;
+        int mButtonPaddingHorizontal = -1;
+
+        SmartSuggestionMeasures(int measuredWidth, int maxChildHeight,
+                int buttonPaddingHorizontal) {
+            this.mMeasuredWidth = measuredWidth;
+            this.mMaxChildHeight = maxChildHeight;
+            this.mButtonPaddingHorizontal = buttonPaddingHorizontal;
+        }
+
+        public SmartSuggestionMeasures clone() {
+            return new SmartSuggestionMeasures(
+                    mMeasuredWidth, mMaxChildHeight, mButtonPaddingHorizontal);
+        }
+    }
+
+    /**
+     * Returns whether our notification contains at least N smart replies (or 0) where N is
+     * determined by {@link SmartReplyConstants}.
+     */
+    private boolean gotEnoughSmartReplies(List<View> smartReplies) {
+        int numShownReplies = 0;
+        for (View smartReplyButton : smartReplies) {
+            final LayoutParams lp = (LayoutParams) smartReplyButton.getLayoutParams();
+            if (lp.show) {
+                numShownReplies++;
+            }
+        }
+        if (numShownReplies == 0
+                || numShownReplies >= mConstants.getMinNumSystemGeneratedReplies()) {
+            // We have enough replies, yay!
+            return true;
+        }
+        return false;
     }
 
     private List<View> filterActionsOrReplies(SmartButtonType buttonType) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index fbc1c20..d80b444 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -39,6 +39,7 @@
 import android.widget.FrameLayout;
 import android.widget.TextClock;
 
+import com.android.keyguard.clock.ClockManager;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.statusbar.StatusBarState;
@@ -51,8 +52,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.function.Consumer;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 // Need to run on the main thread because KeyguardSliceView$Row init checks for
@@ -85,7 +84,7 @@
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getView()).thenReturn(pluginView);
 
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
 
         verify(mClockView).setVisibility(GONE);
         assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
@@ -102,7 +101,7 @@
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getBigClockView()).thenReturn(pluginView);
         // WHEN the plugin is connected
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         // THEN the big clock container is visible and it is the parent of the
         // big clock view.
         assertThat(bigClockContainer.getVisibility()).isEqualTo(VISIBLE);
@@ -112,7 +111,7 @@
     @Test
     public void onPluginConnected_nullView() {
         ClockPlugin plugin = mock(ClockPlugin.class);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         verify(mClockView, never()).setVisibility(GONE);
     }
 
@@ -121,11 +120,11 @@
         // GIVEN a plugin has already connected
         ClockPlugin plugin1 = mock(ClockPlugin.class);
         when(plugin1.getView()).thenReturn(new TextClock(getContext()));
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin1);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin1);
         // WHEN a second plugin is connected
         ClockPlugin plugin2 = mock(ClockPlugin.class);
         when(plugin2.getView()).thenReturn(new TextClock(getContext()));
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin2);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin2);
         // THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
         assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
         assertThat(plugin1.getView().getParent()).isNull();
@@ -137,7 +136,7 @@
         mKeyguardClockSwitch.setDarkAmount(0.5f);
         // WHEN a plugin is connected
         ClockPlugin plugin = mock(ClockPlugin.class);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
         // THEN dark amount should be initalized on the plugin.
         verify(plugin).setDarkAmount(0.5f);
     }
@@ -149,8 +148,8 @@
         when(plugin.getView()).thenReturn(pluginView);
         mClockView.setVisibility(GONE);
 
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(null);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
 
         verify(mClockView).setVisibility(VISIBLE);
         assertThat(plugin.getView().getParent()).isNull();
@@ -167,8 +166,8 @@
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getBigClockView()).thenReturn(pluginView);
         // WHEN the plugin is connected and then disconnected
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(null);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
         // THEN the big lock container is GONE and the big clock view doesn't have
         // a parent.
         assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
@@ -178,8 +177,8 @@
     @Test
     public void onPluginDisconnected_nullView() {
         ClockPlugin plugin = mock(ClockPlugin.class);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(null);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
         verify(mClockView, never()).setVisibility(GONE);
     }
 
@@ -188,13 +187,13 @@
         // GIVEN two plugins are connected
         ClockPlugin plugin1 = mock(ClockPlugin.class);
         when(plugin1.getView()).thenReturn(new TextClock(getContext()));
-        Consumer<ClockPlugin> consumer = mKeyguardClockSwitch.getClockPluginConsumer();
-        consumer.accept(plugin1);
+        ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
+        listener.onClockChanged(plugin1);
         ClockPlugin plugin2 = mock(ClockPlugin.class);
         when(plugin2.getView()).thenReturn(new TextClock(getContext()));
-        consumer.accept(plugin2);
+        listener.onClockChanged(plugin2);
         // WHEN the second plugin is disconnected
-        consumer.accept(null);
+        listener.onClockChanged(null);
         // THEN the default clock should be shown.
         verify(mClockView).setVisibility(VISIBLE);
         assertThat(plugin1.getView().getParent()).isNull();
@@ -213,7 +212,7 @@
         ClockPlugin plugin = mock(ClockPlugin.class);
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getView()).thenReturn(pluginView);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
 
         mKeyguardClockSwitch.setTextColor(Color.WHITE);
 
@@ -237,7 +236,7 @@
         TextClock pluginView = new TextClock(getContext());
         when(plugin.getView()).thenReturn(pluginView);
         Style style = mock(Style.class);
-        mKeyguardClockSwitch.getClockPluginConsumer().accept(plugin);
+        mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
 
         mKeyguardClockSwitch.setStyle(style);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index fa5cf04..60a20cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.bubbles;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.atLeastOnce;
@@ -160,6 +161,12 @@
         stackView.expandStack();
         assertTrue(mBubbleController.isStackExpanded());
 
+        stackView.setExpandedBubble(mRow.getEntry());
+        assertEquals(stackView.getExpandedBubble().getEntry(), mRow.getEntry());
+
+        stackView.setExpandedBubble(mRow2.getEntry());
+        assertEquals(stackView.getExpandedBubble().getEntry(), mRow2.getEntry());
+
         mBubbleController.collapseStack();
         assertFalse(mBubbleController.isStackExpanded());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java b/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java
index b368876..839b5e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dock/DockManagerFake.java
@@ -32,6 +32,11 @@
         this.mCallback = null;
     }
 
+    @Override
+    public boolean isDocked() {
+        return false;
+    }
+
     public void setDockEvent(int event) {
         mCallback.onEvent(event);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index f45500a..e4558df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -36,6 +36,8 @@
         when(params.getPickupVibrationThreshold()).thenReturn(0);
         when(params.getProxCheckBeforePulse()).thenReturn(true);
         when(params.getPickupSubtypePerformsProxCheck(anyInt())).thenReturn(true);
+        when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
+        when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
 
         doneHolder[0] = true;
         return params;
@@ -48,9 +50,14 @@
         when(config.doubleTapGestureEnabled(anyInt())).thenReturn(false);
         when(config.pickupGestureEnabled(anyInt())).thenReturn(false);
         when(config.pulseOnNotificationEnabled(anyInt())).thenReturn(true);
+        when(config.alwaysOnEnabled(anyInt())).thenReturn(false);
 
         when(config.doubleTapSensorType()).thenReturn(null);
+        when(config.tapSensorType()).thenReturn(null);
+        when(config.longPressSensorType()).thenReturn(null);
+
         when(config.dozePickupSensorAvailable()).thenReturn(false);
+        when(config.wakeScreenGestureAvailable()).thenReturn(false);
 
         doneHolder[0] = true;
         return config;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
index 926ff69..0fc0953 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeDockHandlerTest.java
@@ -75,7 +75,7 @@
         mContext.putComponent(DockManager.class, mDockManagerFake);
 
         mDockHandler = new DozeDockHandler(mContext, mMachine, mHost, mConfig,
-                Handler.createAsync(Looper.myLooper()));
+                Handler.createAsync(Looper.myLooper()), mDockManagerFake);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 31fc625..7b358b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -18,8 +18,10 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -34,6 +36,8 @@
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dock.DockManager;
+import com.android.systemui.dock.DockManagerFake;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.wakelock.WakeLock;
 import com.android.systemui.util.wakelock.WakeLockFake;
@@ -59,6 +63,7 @@
     private WakeLock mWakeLock;
     private Instrumentation mInstrumentation;
     private AlarmManager mAlarmManager;
+    private DockManagerFake mDockManagerFake;
 
     @BeforeClass
     public static void setupSuite() {
@@ -76,9 +81,12 @@
         mParameters = DozeConfigurationUtil.createMockParameters();
         mSensors = new FakeSensorManager(mContext);
         mWakeLock = new WakeLockFake();
+        mDockManagerFake = spy(new DockManagerFake());
+        mContext.putComponent(DockManager.class, mDockManagerFake);
 
         mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters,
-                mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true);
+                mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true,
+                mDockManagerFake);
     }
 
     @Test
@@ -102,4 +110,38 @@
         verify(mMachine).requestPulse(anyInt());
     }
 
+    @Test
+    public void testDockEventListener_registerAndUnregister() {
+        mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
+
+        verify(mDockManagerFake).addListener(any());
+
+        mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
+
+        verify(mDockManagerFake).removeListener(any());
+    }
+
+    @Test
+    public void testOnSensor_whenUndockedWithNearAndDoubleTapScreen_shouldNotWakeUp() {
+        mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
+
+        mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP,
+                false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
+                null /* rawValues */);
+
+        verify(mMachine, never()).wakeUp();
+    }
+
+    @Test
+    public void testOnSensor_whenDockedWithNearAndDoubleTapScreen_shouldWakeUp() {
+        doReturn(true).when(mDockManagerFake).isDocked();
+        mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
+
+        mTriggers.onSensor(DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP,
+                false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
+                null /* rawValues */);
+
+        verify(mMachine).wakeUp();
+    }
+
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
index 4b03399..2f6b221 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
@@ -17,6 +17,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 
@@ -27,6 +28,7 @@
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.UiOffloadThread;
@@ -66,7 +68,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
-                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean());
+                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
     }
 
     @Test
@@ -75,7 +77,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
-                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean());
+                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
     }
 
     @Test
@@ -87,7 +89,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
-                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean());
+                eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
     }
 
     @Test
@@ -99,7 +101,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService).onNotificationExpansionChanged(
-                NOTIFICATION_KEY, true, true);
+                NOTIFICATION_KEY, true, true, ExpandableViewState.LOCATION_UNKNOWN);
     }
 
     @Test
@@ -111,7 +113,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService).onNotificationExpansionChanged(
-                NOTIFICATION_KEY, false, true);
+                NOTIFICATION_KEY, false, true, ExpandableViewState.LOCATION_UNKNOWN);
     }
 
     @Test
@@ -123,7 +125,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService).onNotificationExpansionChanged(
-                NOTIFICATION_KEY, false, true);
+                NOTIFICATION_KEY, false, true, ExpandableViewState.LOCATION_UNKNOWN);
     }
 
     @Test
@@ -136,7 +138,7 @@
         waitForUiOffloadThread();
 
         verify(mBarService).onNotificationExpansionChanged(
-                NOTIFICATION_KEY, false, true);
+                NOTIFICATION_KEY, false, true, ExpandableViewState.LOCATION_UNKNOWN);
     }
 
     private NotificationVisibility createNotificationVisibility(String key, boolean visibility) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
index 667a508..4dee438 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
@@ -17,7 +17,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -171,6 +170,19 @@
         ev.recycle();
     }
 
+    @Test
+    public void testViewNotAttachedNoCrash() {
+        View view = mockViewAt(0, 20, 10, 10);
+        when(view.isAttachedToWindow()).thenReturn(false);
+        mNearestTouchFrame.addView(view);
+        mNearestTouchFrame.onMeasure(0, 0);
+
+        MotionEvent ev = MotionEvent.obtain(0, 0, 0, 5 /* x */, 18 /* y */, 0);
+        mNearestTouchFrame.onTouchEvent(ev);
+        verify(view, never()).onTouchEvent(eq(ev));
+        ev.recycle();
+    }
+
     private View mockViewAt(int x, int y, int width, int height) {
         View v = spy(new View(mContext));
         doAnswer(invocation -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index 98d0c6b..9996a9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -95,4 +95,11 @@
     public void testAdd_updatesVisibilityFlags() {
         verify(mStatusBarView).setSystemUiVisibility(anyInt());
     }
+
+    @Test
+    public void testSetForcePluginOpen_beforeStatusBarInitialization() {
+        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+                mActivityManager, mDozeParameters);
+        mStatusBarWindowController.setForcePluginOpen(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
index 3cbf902..03b7c95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
@@ -55,6 +55,9 @@
         resources.addOverride(
                 R.bool.config_smart_replies_in_notifications_edit_choices_before_sending, false);
         resources.addOverride(R.bool.config_smart_replies_in_notifications_show_in_heads_up, true);
+        resources.addOverride(
+                R.integer.config_smart_replies_in_notifications_min_num_system_generated_replies,
+                2);
         mConstants = new SmartReplyConstants(Handler.createAsync(Looper.myLooper()), mContext);
     }
 
@@ -178,6 +181,19 @@
                 Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, flags);
     }
 
+    @Test
+    public void testGetMinNumSystemGeneratedRepliesWithNoConfig() {
+        assertTrue(mConstants.isEnabled());
+        assertEquals(2, mConstants.getMinNumSystemGeneratedReplies());
+    }
+
+    @Test
+    public void testGetMinNumSystemGeneratedRepliesWithValidConfig() {
+        overrideSetting("enabled=true,min_num_system_generated_replies=5");
+        triggerConstantsOnChange();
+        assertEquals(5, mConstants.getMinNumSystemGeneratedReplies());
+    }
+
     private void triggerConstantsOnChange() {
         // Since Settings.Global is mocked in TestableContext, we need to manually trigger the
         // content observer.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 1066bc1..d1c4d01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -96,6 +96,7 @@
     @Mock private SmartReplyController mLogger;
     private NotificationEntry mEntry;
     private Notification mNotification;
+    @Mock private SmartReplyConstants mConstants;
 
     @Mock ActivityStarter mActivityStarter;
     @Mock HeadsUpManager mHeadsUpManager;
@@ -108,10 +109,14 @@
         mDependency.get(KeyguardDismissUtil.class).setDismissHandler(action -> action.onDismiss());
         mDependency.injectMockDependency(ShadeController.class);
         mDependency.injectTestDependency(ActivityStarter.class, mActivityStarter);
+        mDependency.injectTestDependency(SmartReplyConstants.class, mConstants);
 
         mContainer = new View(mContext, null);
         mView = SmartReplyView.inflate(mContext, null);
 
+        // Any number of replies are fine.
+        when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(0);
+        when(mConstants.getMaxSqueezeRemeasureAttempts()).thenReturn(3);
 
         final Resources res = mContext.getResources();
         mSingleLinePaddingHorizontal = res.getDimensionPixelSize(
@@ -403,7 +408,7 @@
     }
 
     private void setSmartReplies(CharSequence[] choices) {
-        setSmartReplies(choices, false);
+        setSmartReplies(choices, false /* fromAssistant */);
     }
 
     private void setSmartReplies(CharSequence[] choices, boolean fromAssistant) {
@@ -440,9 +445,14 @@
     }
 
     private void setSmartRepliesAndActions(CharSequence[] choices, String[] actionTitles) {
-        setSmartReplies(choices);
+        setSmartRepliesAndActions(choices, actionTitles, false /* fromAssistant */);
+    }
+
+    private void setSmartRepliesAndActions(
+            CharSequence[] choices, String[] actionTitles, boolean fromAssistant) {
+        setSmartReplies(choices, fromAssistant);
         mView.addSmartActions(
-                new SmartReplyView.SmartActions(createActions(actionTitles), false),
+                new SmartReplyView.SmartActions(createActions(actionTitles), fromAssistant),
                 mLogger,
                 mEntry,
                 mHeadsUpManager);
@@ -943,4 +953,78 @@
                 expectedView.getChildAt(3), mView.getChildAt(4)); // a1
         assertReplyButtonHidden(mView.getChildAt(5)); // long action
     }
+
+    @Test
+    public void testMeasure_minNumSystemGeneratedSmartReplies_notEnoughReplies() {
+        when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(3);
+
+        // Add 2 replies when the minimum is 3 -> we should end up with 0 replies.
+        String[] choices = new String[] {"reply1", "reply2"};
+        String[] actions = new String[] {"action1"};
+
+        ViewGroup expectedView = buildExpectedView(new String[] {}, 1,
+                createActions(new String[] {"action1"}));
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setSmartRepliesAndActions(choices, actions, true /* fromAssistant */);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        // smart replies
+        assertReplyButtonHidden(mView.getChildAt(0));
+        assertReplyButtonHidden(mView.getChildAt(1));
+        // smart actions
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(2));
+    }
+
+    @Test
+    public void testMeasure_minNumSystemGeneratedSmartReplies_enoughReplies() {
+        when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(2);
+
+        // Add 2 replies when the minimum is 3 -> we should end up with 0 replies.
+        String[] choices = new String[] {"reply1", "reply2"};
+        String[] actions = new String[] {"action1"};
+
+        ViewGroup expectedView = buildExpectedView(new String[] {"reply1", "reply2"}, 1,
+                createActions(new String[] {"action1"}));
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setSmartRepliesAndActions(choices, actions, true /* fromAssistant */);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        // smart replies
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(0));
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(1), mView.getChildAt(1));
+        // smart actions
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(2), mView.getChildAt(2));
+    }
+
+    /**
+     * Ensure actions that are squeezed when shown together with smart replies are unsqueezed if the
+     * replies are never added (because of the SmartReplyConstants.getMinNumSystemGeneratedReplies()
+     * flag).
+     */
+    @Test
+    public void testMeasure_minNumSystemGeneratedSmartReplies_unSqueezeActions() {
+        when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(2);
+
+        // Add 2 replies when the minimum is 3 -> we should end up with 0 replies.
+        String[] choices = new String[] {"This is a very long two-line reply."};
+        String[] actions = new String[] {"Short action"};
+
+        // The action should be displayed on one line only - since it fits!
+        ViewGroup expectedView = buildExpectedView(new String[] {}, 1 /* lineCount */,
+                createActions(new String[] {"Short action"}));
+        expectedView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        setSmartRepliesAndActions(choices, actions, true /* fromAssistant */);
+        mView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
+
+        assertEqualMeasures(expectedView, mView);
+        // smart replies
+        assertReplyButtonHidden(mView.getChildAt(0));
+        // smart actions
+        assertReplyButtonShownWithEqualMeasures(expectedView.getChildAt(0), mView.getChildAt(1));
+    }
 }
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 8261fe8..9b0a443 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -73,6 +73,10 @@
 
     // The view switched to summary mode (most relevant for notifications)
     TYPE_COLLAPSE = 14;
+
+    // The notification was adjusted by the assistant. Enum value is
+    // out of sequence due to b/122737498.
+    TYPE_NOTIFICATION_ASSISTANT_ADJUSTMENT = 1573;
   }
 
   // Types of alerts, as bit field values
@@ -232,6 +236,17 @@
     BLOCKING_HELPER_CLICK_UNDO = 7;
   }
 
+  // The (visual) location of a Notification.
+  enum NotificationLocation {
+    LOCATION_UNKNOWN = 0;
+    LOCATION_FIRST_HEADS_UP = 1; // visible heads-up
+    LOCATION_HIDDEN_TOP = 2; // hidden/scrolled away on the top
+    LOCATION_MAIN_AREA = 3; // visible in the shade
+    LOCATION_BOTTOM_STACK_PEEKING = 4; // in the bottom stack, and peeking
+    LOCATION_BOTTOM_STACK_HIDDEN = 5; // in the bottom stack, and hidden
+    LOCATION_GONE = 6; // the view isn't laid out at all
+  }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -6820,6 +6835,17 @@
     // OS: Q
     MOBILE_NETWORK_LIST = 1627;
 
+    // OPEN: Settings > Display > Adaptive sleep
+    // OS: Q
+    SETTINGS_ADAPTIVE_SLEEP = 1628;
+
+    // Tagged data for SMART_REPLY_VISIBLE and NOTIFICATION_ITEM_ACTION.
+    // The UI location of the notification containing the smart suggestions.
+    // This is a NotificationLocation object (see the NotificationLocation
+    // enum).
+    // OS: Q
+    NOTIFICATION_LOCATION = 1629;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 1212676..6ff2b35 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -216,9 +216,9 @@
     // Package: android
     NOTE_SOFTAP_CONFIG_CHANGED = 50;
 
-    // Notify the user that connected to app suggested network.
+    // Notify the user that an app suggested network is available for connection.
     // Package: android
-    NOTE_CONNECTED_TO_NETWORK_SUGGESTION = 51;
+    NOTE_NETWORK_SUGGESTION_AVAILABLE = 51;
 
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index add5e5f..0b4c01e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -46,6 +46,7 @@
 import android.content.pm.Signature;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.hardware.location.ActivityRecognitionHardware;
 import android.location.Address;
 import android.location.Criteria;
 import android.location.GeocoderParams;
@@ -92,6 +93,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.location.AbstractLocationProvider;
+import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GeofenceProxy;
@@ -736,6 +738,25 @@
             Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
         }
 
+        // bind to hardware activity recognition
+        boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
+        ActivityRecognitionHardware activityRecognitionHardware = null;
+        if (activityRecognitionHardwareIsSupported) {
+            activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
+        } else {
+            Slog.d(TAG, "Hardware Activity-Recognition not supported.");
+        }
+        ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
+                mContext,
+                activityRecognitionHardwareIsSupported,
+                activityRecognitionHardware,
+                com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
+                com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
+                com.android.internal.R.array.config_locationProviderPackageNames);
+        if (proxy == null) {
+            Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
+        }
+
         String[] testProviderStrings = resources.getStringArray(
                 com.android.internal.R.array.config_testLocationProviders);
         for (String testProviderString : testProviderStrings) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 65aacdc..353749f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -45,6 +45,7 @@
 import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.StatsLog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
@@ -157,6 +158,9 @@
     static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
     static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
 
+    // log latency metrics for ordered broadcasts during BOOT_COMPLETED processing
+    boolean mLogLatencyMetrics = true;
+
     final BroadcastHandler mHandler;
 
     private final class BroadcastHandler extends Handler {
@@ -941,6 +945,12 @@
                     // adjustments.
                     mService.updateOomAdjLocked();
                 }
+
+                // when we have no more ordered broadcast on this queue, stop logging
+                if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
+                    mLogLatencyMetrics = false;
+                }
+
                 return;
             }
             r = mOrderedBroadcasts.get(0);
@@ -1036,6 +1046,13 @@
         if (recIdx == 0) {
             r.dispatchTime = r.receiverTime;
             r.dispatchClockTime = System.currentTimeMillis();
+
+            if (mLogLatencyMetrics) {
+                StatsLog.write(
+                        StatsLog.BROADCAST_DISPATCH_LATENCY_REPORTED,
+                        r.dispatchClockTime - r.enqueueClockTime);
+            }
+
             if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                     createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index bcce052..c981e68 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -240,6 +240,8 @@
 
     private final LockPatternUtils mLockPatternUtils;
 
+    volatile boolean mBootCompleted;
+
     UserController(ActivityManagerService service) {
         this(new Injector(service));
     }
@@ -567,6 +569,7 @@
                             Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                             throws RemoteException {
                         Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u" + userId);
+                        mBootCompleted = true;
                     }
                 }, 0, null, null,
                 new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index f60d6b0..8f1befe 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -73,7 +73,6 @@
 
     private final Context mContext;
     private final PowerManager mPowerManager;
-    private final ActivityManager mActivityManager;
     private final Object mLock;
     @GuardedBy("mLock")
     private final SparseArray<UserState> mUserStates = new SparseArray<>();
@@ -85,7 +84,6 @@
         super(context);
         mContext = Preconditions.checkNotNull(context);
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mLock = new Object();
         mAttentionHandler = new AttentionHandler();
     }
@@ -96,7 +94,7 @@
     }
 
     @Override
-    public void onStopUser(int userId) {
+    public void onSwitchUser(int userId) {
         cancelAndUnbindLocked(peekUserStateLocked(userId),
                 AttentionService.ATTENTION_FAILURE_UNKNOWN);
     }
@@ -201,11 +199,20 @@
 
     /** Cancels the specified attention check. */
     public void cancelAttentionCheck(int requestCode) {
-        final UserState userState = getOrCreateCurrentUserStateLocked();
-        try {
-            userState.mService.cancelAttentionCheck(requestCode);
-        } catch (RemoteException e) {
-            Slog.e(LOG_TAG, "Cannot call into the AttentionService");
+        synchronized (mLock) {
+            final UserState userState = getOrCreateCurrentUserStateLocked();
+            if (userState.mService == null) {
+                if (userState.mPendingAttentionCheck != null
+                        && userState.mPendingAttentionCheck.mRequestCode == requestCode) {
+                    userState.mPendingAttentionCheck = null;
+                }
+                return;
+            }
+            try {
+                userState.mService.cancelAttentionCheck(requestCode);
+            } catch (RemoteException e) {
+                Slog.e(LOG_TAG, "Cannot call into the AttentionService");
+            }
         }
     }
 
@@ -224,7 +231,7 @@
 
     @GuardedBy("mLock")
     private UserState getOrCreateCurrentUserStateLocked() {
-        return getOrCreateUserStateLocked(mActivityManager.getCurrentUser());
+        return getOrCreateUserStateLocked(ActivityManager.getCurrentUser());
     }
 
     @GuardedBy("mLock")
@@ -239,7 +246,7 @@
 
     @GuardedBy("mLock")
     UserState peekCurrentUserStateLocked() {
-        return peekUserStateLocked(mActivityManager.getCurrentUser());
+        return peekUserStateLocked(ActivityManager.getCurrentUser());
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 11299b6..706fd55 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4746,12 +4746,18 @@
 
     private int getA2dpCodec(BluetoothDevice device) {
         synchronized (mA2dpAvrcpLock) {
-            if (mA2dp != null) {
-                BluetoothCodecStatus btCodecStatus = mA2dp.getCodecStatus(device);
-                BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
-                return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType());
+            if (mA2dp == null) {
+                return AudioSystem.AUDIO_FORMAT_DEFAULT;
             }
-            return AudioSystem.AUDIO_FORMAT_DEFAULT;
+            BluetoothCodecStatus btCodecStatus = mA2dp.getCodecStatus(device);
+            if (btCodecStatus == null) {
+                return AudioSystem.AUDIO_FORMAT_DEFAULT;
+            }
+            BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig();
+            if (btCodecConfig == null) {
+                return AudioSystem.AUDIO_FORMAT_DEFAULT;
+            }
+            return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType());
         }
     }
 
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 9223739..3a58160 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -28,6 +28,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
+import android.annotation.UserIdInt;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -51,6 +52,7 @@
 import android.provider.Settings.System;
 import android.util.MathUtils;
 import android.util.Slog;
+import android.view.SurfaceControl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
 
@@ -866,6 +868,12 @@
         if (mDisplayWhiteBalanceListener != null && oldActivated != activated) {
             mDisplayWhiteBalanceListener.onDisplayWhiteBalanceStatusChanged(activated);
         }
+
+        // If disabled, clear the tint. If enabled, do nothing more here and let the next
+        // temperature update set the correct tint.
+        if (!activated) {
+            applyTint(mDisplayWhiteBalanceTintController, false);
+        }
     }
 
     private boolean isDisplayWhiteBalanceSettingEnabled() {
@@ -878,6 +886,21 @@
         return dtm.isDeviceColorManaged();
     }
 
+    private int getTransformCapabilitiesInternal() {
+        int availabilityFlags = ColorDisplayManager.CAPABILITY_NONE;
+        if (SurfaceControl.getProtectedContentSupport()) {
+            availabilityFlags |= ColorDisplayManager.CAPABILITY_PROTECTED_CONTENT;
+        }
+        final Resources res = getContext().getResources();
+        if (res.getBoolean(R.bool.config_setColorTransformAccelerated)) {
+            availabilityFlags |= ColorDisplayManager.CAPABILITY_HARDWARE_ACCELERATION_GLOBAL;
+        }
+        if (res.getBoolean(R.bool.config_setColorTransformAcceleratedPerLayer)) {
+            availabilityFlags |= ColorDisplayManager.CAPABILITY_HARDWARE_ACCELERATION_PER_APP;
+        }
+        return availabilityFlags;
+    }
+
     /**
      * Returns the last time the night display transform activation state was changed, or {@link
      * LocalDateTime#MIN} if night display has never been activated.
@@ -1226,10 +1249,10 @@
          * Adds a {@link WeakReference<ColorTransformController>} for a newly started activity, and
          * invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed.
          */
-        public boolean attachColorTransformController(String packageName, int uid,
+        public boolean attachColorTransformController(String packageName, @UserIdInt int userId,
                 WeakReference<ColorTransformController> controller) {
             return mAppSaturationController
-                    .addColorTransformController(packageName, uid, controller);
+                    .addColorTransformController(packageName, userId, controller);
         }
     }
 
@@ -1318,6 +1341,18 @@
             }
         }
 
+        public int getTransformCapabilities() {
+            getContext().enforceCallingPermission(
+                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+                    "Permission required to query transform capabilities");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return getTransformCapabilitiesInternal();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 63214ed..cac1a95 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -268,7 +268,7 @@
         mTvSystemAudioModeSupport = false;
         // Record the last state of System Audio Control before going to standby
         synchronized (mLock) {
-            mService.writeStringSetting(
+            mService.writeStringSystemProperty(
                     Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL,
                     mSystemAudioActivated ? "true" : "false");
         }
@@ -330,7 +330,7 @@
     @ServiceThreadOnly
     protected void setPreferredAddress(int addr) {
         assertRunOnServiceThread();
-        mService.writeStringSetting(
+        mService.writeStringSystemProperty(
                 Constants.PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM, String.valueOf(addr));
     }
 
@@ -469,7 +469,7 @@
     protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
         assertRunOnServiceThread();
         removeAction(ArcInitiationActionFromAvr.class);
-        if (!mService.readBooleanSetting(Constants.PROPERTY_ARC_SUPPORT, true)) {
+        if (!mService.readBooleanSystemProperty(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");
@@ -829,7 +829,7 @@
         boolean currentMuteStatus =
                 mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
         if (currentMuteStatus == newSystemAudioMode) {
-            if (mService.readBooleanSetting(
+            if (mService.readBooleanSystemProperty(
                     Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true)
                             || newSystemAudioMode) {
                 mService.getAudioManager()
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 7a0c279..ef7d241 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -100,7 +100,7 @@
     @ServiceThreadOnly
     protected void setPreferredAddress(int addr) {
         assertRunOnServiceThread();
-        mService.writeStringSetting(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK,
+        mService.writeStringSystemProperty(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK,
                 String.valueOf(addr));
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 46219d5..f3a1e46 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -657,9 +657,13 @@
         Global.putInt(cr, key, toInt(value));
     }
 
-    void writeStringSetting(String key, String value) {
-        ContentResolver cr = getContext().getContentResolver();
-        Global.putString(cr, key, value);
+    void writeStringSystemProperty(String key, String value) {
+        SystemProperties.set(key, value);
+    }
+
+    @VisibleForTesting
+    boolean readBooleanSystemProperty(String key, boolean defVal) {
+        return SystemProperties.getBoolean(key, defVal);
     }
 
     private void initializeCec(int initiatedBy) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2d197bb..52074a7 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1607,7 +1607,7 @@
     // 1) it comes from the system process
     // 2) the calling process' user id is identical to the current user id IMMS thinks.
     @GuardedBy("mMethodMap")
-    private boolean calledFromValidUserLocked(boolean allowCrossProfileAccess) {
+    private boolean calledFromValidUserLocked() {
         final int uid = Binder.getCallingUid();
         final int userId = UserHandle.getUserId(uid);
         if (DEBUG) {
@@ -1623,7 +1623,7 @@
         if (userId == mSettings.getCurrentUserId()) {
             return true;
         }
-        if (allowCrossProfileAccess && mSettings.isCurrentProfile(userId)) {
+        if (!PER_PROFILE_IME_ENABLED && mSettings.isCurrentProfile(userId)) {
             return true;
         }
 
@@ -2651,7 +2651,7 @@
             ResultReceiver resultReceiver) {
         int uid = Binder.getCallingUid();
         synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return false;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -2736,7 +2736,7 @@
             ResultReceiver resultReceiver) {
         int uid = Binder.getCallingUid();
         synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return false;
             }
             final long ident = Binder.clearCallingIdentity();
@@ -3087,7 +3087,7 @@
     public void showInputMethodPickerFromClient(
             IInputMethodClient client, int auxiliarySubtypeMode) {
         synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return;
             }
             if(!canShowInputMethodPickerLocked(client)) {
@@ -3159,7 +3159,7 @@
             IInputMethodClient client, String inputMethodId) {
         synchronized (mMethodMap) {
             // TODO(yukawa): Should we verify the display ID?
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return;
             }
             executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
@@ -3274,7 +3274,7 @@
     @Override
     public InputMethodSubtype getLastInputMethodSubtype() {
         synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return null;
             }
             final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
@@ -3312,7 +3312,7 @@
             }
         }
         synchronized (mMethodMap) {
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return;
             }
             if (!mSystemReady) {
@@ -4158,7 +4158,7 @@
     public InputMethodSubtype getCurrentInputMethodSubtype() {
         synchronized (mMethodMap) {
             // TODO: Make this work even for non-current users?
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return null;
             }
             return getCurrentInputMethodSubtypeLocked();
@@ -4208,7 +4208,7 @@
     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
         synchronized (mMethodMap) {
             // TODO: Make this work even for non-current users?
-            if (!calledFromValidUserLocked(!PER_PROFILE_IME_ENABLED)) {
+            if (!calledFromValidUserLocked()) {
                 return false;
             }
             if (subtype != null && mCurMethodId != null) {
diff --git a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
new file mode 100644
index 0000000..22fabb2
--- /dev/null
+++ b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.server.location;
+
+import android.content.Context;
+import android.hardware.location.ActivityRecognitionHardware;
+import android.hardware.location.IActivityRecognitionHardwareClient;
+import android.hardware.location.IActivityRecognitionHardwareWatcher;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.server.ServiceWatcher;
+
+/**
+ * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
+ *
+ * @hide
+ */
+public class ActivityRecognitionProxy {
+
+    private static final String TAG = "ActivityRecognitionProxy";
+
+    /**
+     * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
+     *
+     * @return An instance of the proxy if it could be bound, null otherwise.
+     */
+    public static ActivityRecognitionProxy createAndBind(
+            Context context,
+            boolean activityRecognitionHardwareIsSupported,
+            ActivityRecognitionHardware activityRecognitionHardware,
+            int overlaySwitchResId,
+            int defaultServicePackageNameResId,
+            int initialPackageNameResId) {
+        ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
+                context,
+                activityRecognitionHardwareIsSupported,
+                activityRecognitionHardware,
+                overlaySwitchResId,
+                defaultServicePackageNameResId,
+                initialPackageNameResId);
+
+        if (activityRecognitionProxy.mServiceWatcher.start()) {
+            return activityRecognitionProxy;
+        } else {
+            return null;
+        }
+    }
+
+    private final ServiceWatcher mServiceWatcher;
+    private final boolean mIsSupported;
+    private final ActivityRecognitionHardware mInstance;
+
+    private ActivityRecognitionProxy(
+            Context context,
+            boolean activityRecognitionHardwareIsSupported,
+            ActivityRecognitionHardware activityRecognitionHardware,
+            int overlaySwitchResId,
+            int defaultServicePackageNameResId,
+            int initialPackageNameResId) {
+        mIsSupported = activityRecognitionHardwareIsSupported;
+        mInstance = activityRecognitionHardware;
+
+        mServiceWatcher = new ServiceWatcher(
+                context,
+                TAG,
+                "com.android.location.service.ActivityRecognitionProvider",
+                overlaySwitchResId,
+                defaultServicePackageNameResId,
+                initialPackageNameResId,
+                BackgroundThread.getHandler()) {
+            @Override
+            protected void onBind() {
+                runOnBinder(ActivityRecognitionProxy.this::initializeService);
+            }
+        };
+    }
+
+    private void initializeService(IBinder binder) {
+        try {
+            String descriptor = binder.getInterfaceDescriptor();
+
+            if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(
+                    descriptor)) {
+                IActivityRecognitionHardwareWatcher watcher =
+                        IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
+                if (mInstance != null) {
+                    watcher.onInstanceChanged(mInstance);
+                }
+            } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
+                    .equals(descriptor)) {
+                IActivityRecognitionHardwareClient client =
+                        IActivityRecognitionHardwareClient.Stub.asInterface(binder);
+                client.onAvailabilityChanged(mIsSupported, mInstance);
+            } else {
+                Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index ee60daa..c2dc554 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -42,7 +42,8 @@
     void onNotificationVisibilityChanged(
             NotificationVisibility[] newlyVisibleKeys,
             NotificationVisibility[] noLongerVisibleKeys);
-    void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
+    void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded,
+            int notificationLocation);
     void onNotificationDirectReplied(String key);
     void onNotificationSettingsViewed(String key);
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 20c4da4..47a5597 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -868,7 +868,7 @@
 
         @Override
         public void onNotificationExpansionChanged(String key,
-                boolean userAction, boolean expanded) {
+                boolean userAction, boolean expanded, int notificationLocation) {
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 5598741..02fc51f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -1263,7 +1263,7 @@
     public LogMaker getAdjustmentLogMaker() {
         return getLogMaker()
                 .setCategory(MetricsEvent.NOTIFICATION_ITEM)
-                .setType(MetricsEvent.NOTIFICATION_ASSISTANT_ADJUSTMENT);
+                .setType(MetricsEvent.TYPE_NOTIFICATION_ASSISTANT_ADJUSTMENT);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index bf4e272..0ab2a73 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -310,7 +310,6 @@
             in.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type;
-            PackageInstallerSession currentSession = null;
             while ((type = in.next()) != END_DOCUMENT) {
                 if (type == START_TAG) {
                     final String tag = in.getName();
@@ -320,9 +319,7 @@
                             session = PackageInstallerSession.readFromXml(in, mInternalCallback,
                                     mContext, mPm, mInstallThread.getLooper(), mStagingManager,
                                     mSessionsDir, this);
-                            currentSession = session;
                         } catch (Exception e) {
-                            currentSession = null;
                             Slog.e(TAG, "Could not read session", e);
                             continue;
                         }
@@ -347,10 +344,6 @@
                             addHistoricalSessionLocked(session);
                         }
                         mAllocatedSessions.put(session.sessionId, true);
-                    } else if (currentSession != null
-                            && PackageInstallerSession.TAG_CHILD_SESSION.equals(tag)) {
-                        currentSession.addChildSessionIdInternal(
-                                PackageInstallerSession.readChildSessionIdFromXml(in));
                     }
                 }
             }
@@ -1132,6 +1125,7 @@
 
         public void onStagedSessionChanged(PackageInstallerSession session) {
             writeSessionsAsync();
+            // TODO(b/118865310): don't send broadcast if system is not ready.
             mPm.sendSessionUpdatedBroadcast(session.generateInfo(false), session.userId);
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 12d335d..b8825bb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -992,8 +992,12 @@
 
         // Read transfers from the original owner stay open, but as the session's data
         // cannot be modified anymore, there is no leak of information. For staged sessions,
-        // further validation may be performed by the staging manager.
+        // further validation is performed by the staging manager.
         if (!params.isMultiPackage) {
+            if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+                // For APEX, validation is done by StagingManager post-commit.
+                return;
+            }
             final PackageInfo pkgInfo = mPm.getPackageInfo(
                     params.appPackageName, PackageManager.GET_SIGNATURES
                             | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
@@ -1001,16 +1005,7 @@
             resolveStageDirLocked();
 
             try {
-                if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
-                    // TODO(b/118865310): Remove this when APEX validation is done via
-                    //                    StagingManager.
-                    validateApexInstallLocked(pkgInfo);
-                } else {
-                    // Verify that stage looks sane with respect to existing application.
-                    // This currently only ensures packageName, versionCode, and certificate
-                    // consistency.
-                    validateApkInstallLocked(pkgInfo);
-                }
+                validateApkInstallLocked(pkgInfo);
             } catch (PackageManagerException e) {
                 throw e;
             } catch (Throwable e) {
@@ -1301,54 +1296,6 @@
                 (params.installFlags & PackageManager.DONT_KILL_APP) != 0;
     }
 
-    @GuardedBy("mLock")
-    private void validateApexInstallLocked(@Nullable PackageInfo pkgInfo)
-            throws PackageManagerException {
-        mResolvedStagedFiles.clear();
-        mResolvedInheritedFiles.clear();
-
-        try {
-            resolveStageDirLocked();
-        } catch (IOException e) {
-            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
-                "Failed to resolve stage location", e);
-        }
-
-        final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
-        if (ArrayUtils.isEmpty(addedFiles)) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
-        }
-
-        if (addedFiles.length > 1) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
-                "Only one APEX file at a time might be installed");
-        }
-        File addedFile = addedFiles[0];
-        final ApkLite apk;
-        try {
-            apk = PackageParser.parseApkLite(
-                addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
-        } catch (PackageParserException e) {
-            throw PackageManagerException.from(e);
-        }
-
-        mPackageName = apk.packageName;
-        mVersionCode = apk.getLongVersionCode();
-        mSigningDetails = apk.signingDetails;
-        mResolvedBaseFile = addedFile;
-
-        // STOPSHIP: Ensure that we remove the non-staged version of APEX installs in production
-        // because we currently do not verify that signatures are consistent with the previously
-        // installed version in that case.
-        //
-        // When that happens, this hack can be reverted and we can rely on APEXd to map between
-        // APEX files and their package names instead of parsing it out of the AndroidManifest
-        // such as here.
-        if (params.appPackageName == null) {
-            params.appPackageName = mPackageName;
-        }
-    }
-
     /**
      * Validate install by confirming that all application packages are have
      * consistent package name, version code, and signing certificates.
@@ -1911,22 +1858,30 @@
     }
 
     @Override
-    public void addChildSessionId(int sessionId) {
-        final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
-        if (session == null) {
+    public void addChildSessionId(int childSessionId) {
+        final PackageInstallerSession childSession = mSessionProvider.getSession(childSessionId);
+        if (childSession == null) {
             throw new RemoteException("Unable to add child.",
-                    new PackageManagerException("Child session " + sessionId + " does not exist"),
+                    new PackageManagerException("Child session " + childSessionId
+                            + " does not exist"),
+                    false, true).rethrowAsRuntimeException();
+        }
+        // Session groups must be consistent wrt to isStaged parameter. Non-staging session
+        // cannot be grouped with staging sessions.
+        if (this.params.isStaged ^ childSession.params.isStaged) {
+            throw new RemoteException("Unable to add child.",
+                    new PackageManagerException("Child session " + childSessionId
+                            + " and parent session " + this.sessionId + " do not have consistent"
+                            + " staging session settings."),
                     false, true).rethrowAsRuntimeException();
         }
         synchronized (mLock) {
-            final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+            final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
             if (indexOfSession >= 0) {
                 return;
             }
-            session.setParentSessionId(this.sessionId);
-            // TODO: sanity check, if parent session is staged then child session should be
-            //       marked as staged.
-            addChildSessionIdInternal(sessionId);
+            childSession.setParentSessionId(this.sessionId);
+            addChildSessionIdInternal(childSessionId);
         }
     }
 
@@ -2057,6 +2012,11 @@
         return mStagedSessionFailed;
     }
 
+    /** {@hide} */
+    @StagedSessionErrorCode int getStagedSessionErrorCode() {
+        return mStagedSessionErrorCode;
+    }
+
     private void destroyInternal() {
         synchronized (mLock) {
             mSealed = true;
@@ -2221,35 +2181,6 @@
         out.endTag(null, TAG_SESSION);
     }
 
-    private static String[] readGrantedRuntimePermissions(XmlPullParser in)
-            throws IOException, XmlPullParserException {
-        List<String> permissions = null;
-
-        final int outerDepth = in.getDepth();
-        int type;
-        while ((type = in.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || in.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-            if (TAG_GRANTED_RUNTIME_PERMISSION.equals(in.getName())) {
-                String permission = readStringAttribute(in, ATTR_NAME);
-                if (permissions == null) {
-                    permissions = new ArrayList<>();
-                }
-                permissions.add(permission);
-            }
-        }
-
-        if (permissions == null) {
-            return null;
-        }
-
-        String[] permissionsArray = new String[permissions.size()];
-        permissions.toArray(permissionsArray);
-        return permissionsArray;
-    }
-
     // Sanity check to be performed when the session is restored from an external file. Only one
     // of the session states should be true, or none of them.
     private static boolean isStagedSessionStateValid(boolean isReady, boolean isApplied,
@@ -2273,8 +2204,6 @@
      * @param sessionProvider
      * @return The newly created session
      */
-    // TODO(patb,109941548): modify readFromXml to consume to the next tag session tag so we
-    //                       can have a complete session for the constructor
     public static PackageInstallerSession readFromXml(@NonNull XmlPullParser in,
             @NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
             @NonNull PackageManagerService pm, Looper installerThread,
@@ -2314,8 +2243,6 @@
         params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
         params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
 
-        params.grantedRuntimePermissions = readGrantedRuntimePermissions(in);
-
         final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
         if (appIconFile.exists()) {
             params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
@@ -2324,16 +2251,51 @@
         final boolean isReady = readBooleanAttribute(in, ATTR_IS_READY);
         final boolean isFailed = readBooleanAttribute(in, ATTR_IS_FAILED);
         final boolean isApplied = readBooleanAttribute(in, ATTR_IS_APPLIED);
-        final int stagedSessionErrorCode = readIntAttribute(in, ATTR_STAGED_SESSION_ERROR_CODE);
+        final int stagedSessionErrorCode = readIntAttribute(in, ATTR_STAGED_SESSION_ERROR_CODE,
+                SessionInfo.NO_ERROR);
 
         if (!isStagedSessionStateValid(isReady, isApplied, isFailed)) {
             throw new IllegalArgumentException("Can't restore staged session with invalid state.");
         }
 
+        // Parse sub tags of this session, typically used for repeated values / arrays.
+        // Sub tags can come in any order, therefore we need to keep track of what we find while
+        // parsing and only set the right values at the end.
+
+        // Store the current depth. We should stop parsing when we reach an end tag at the same
+        // depth.
+        List<String> permissions = new ArrayList<>();
+        List<Integer> childSessionIds = new ArrayList<>();
+        int outerDepth = in.getDepth();
+        int type;
+        while ((type = in.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || in.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            if (TAG_GRANTED_RUNTIME_PERMISSION.equals(in.getName())) {
+                permissions.add(readStringAttribute(in, ATTR_NAME));
+            }
+            if (TAG_CHILD_SESSION.equals(in.getName())) {
+                childSessionIds.add(readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID));
+            }
+        }
+
+        if (permissions.size() > 0) {
+            params.grantedRuntimePermissions = permissions.stream().toArray(String[]::new);
+        }
+
+        int[] childSessionIdsArray;
+        if (childSessionIds.size() > 0) {
+            childSessionIdsArray = childSessionIds.stream().mapToInt(i -> i).toArray();
+        } else {
+            childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY;
+        }
+
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 installerThread, stagingManager, sessionId, userId, installerPackageName,
                 installerUid, params, createdMillis, stageDir, stageCid, prepared, sealed,
-                EMPTY_CHILD_SESSION_ARRAY, parentSessionId, isReady, isFailed, isApplied,
+                childSessionIdsArray, parentSessionId, isReady, isFailed, isApplied,
                 stagedSessionErrorCode);
     }
 
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 7bab0bb..5311c2a 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -41,7 +41,9 @@
 import com.android.internal.os.BackgroundThread;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * This class handles staged install sessions, i.e. install sessions that require packages to
@@ -126,12 +128,24 @@
         return false;
     }
 
-    private static boolean submitSessionToApexService(int sessionId, ApexInfoList apexInfoList) {
+    private static boolean submitSessionToApexService(@NonNull PackageInstallerSession session,
+                                                      List<PackageInstallerSession> childSessions,
+                                                      ApexInfoList apexInfoList) {
+        return sendSubmitStagedSessionRequest(
+                session.sessionId,
+                childSessions != null
+                        ? childSessions.stream().mapToInt(s -> s.sessionId).toArray() :
+                        new int[]{},
+                apexInfoList);
+    }
+
+    private static boolean sendSubmitStagedSessionRequest(
+            int sessionId, int[] childSessionIds, ApexInfoList apexInfoList) {
         final IApexService apex = IApexService.Stub.asInterface(
                 ServiceManager.getService("apexservice"));
         boolean success;
         try {
-            success = apex.submitStagedSession(sessionId, new int[0], apexInfoList);
+            success = apex.submitStagedSession(sessionId, childSessionIds, apexInfoList);
         } catch (RemoteException re) {
             Slog.e(TAG, "Unable to contact apexservice", re);
             return false;
@@ -139,31 +153,49 @@
         return success;
     }
 
+    private static boolean isApexSession(@NonNull PackageInstallerSession session) {
+        return (session.params.installFlags & PackageManager.INSTALL_APEX) != 0;
+    }
+
     private void preRebootVerification(@NonNull PackageInstallerSession session) {
         boolean success = true;
-        if ((session.params.installFlags & PackageManager.INSTALL_APEX) != 0) {
 
-            final ApexInfoList apexInfoList = new ApexInfoList();
+        final ApexInfoList apexInfoList = new ApexInfoList();
+        // APEX checks. For single-package sessions, check if they contain an APEX. For
+        // multi-package sessions, find all the child sessions that contain an APEX.
+        if (!session.isMultiPackage()
+                && isApexSession(session)) {
+            success = submitSessionToApexService(session, null, apexInfoList);
+        } else if (session.isMultiPackage()) {
+            List<PackageInstallerSession> childSessions =
+                    Arrays.stream(session.getChildSessionIds())
+                            // Retrieve cached sessions matching ids.
+                            .mapToObj(i -> mStagedSessions.get(i))
+                            // Filter only the ones containing APEX.
+                            .filter(childSession -> isApexSession(childSession))
+                            .collect(Collectors.toList());
+            if (!childSessions.isEmpty()) {
+                success = submitSessionToApexService(session, childSessions, apexInfoList);
+            } // else this is a staged multi-package session with no APEX files.
+        }
 
-            if (!submitSessionToApexService(session.sessionId, apexInfoList)) {
-                success = false;
-            } else {
-                // For APEXes, we validate the signature here before we mark the session as ready,
-                // so we fail the session early if there is a signature mismatch. For APKs, the
-                // signature verification will be done by the package manager at the point at which
-                // it applies the staged install.
-                //
-                // TODO: Decide whether we want to fail fast by detecting signature mismatches right
-                // away.
-                for (ApexInfo apexPackage : apexInfoList.apexInfos) {
-                    if (!validateApexSignatureLocked(apexPackage.packagePath,
-                            apexPackage.packageName)) {
-                        success = false;
-                        break;
-                    }
+        if (success && (apexInfoList.apexInfos.length > 0)) {
+            // For APEXes, we validate the signature here before we mark the session as ready,
+            // so we fail the session early if there is a signature mismatch. For APKs, the
+            // signature verification will be done by the package manager at the point at which
+            // it applies the staged install.
+            //
+            // TODO: Decide whether we want to fail fast by detecting signature mismatches for APKs,
+            // right away.
+            for (ApexInfo apexPackage : apexInfoList.apexInfos) {
+                if (!validateApexSignatureLocked(apexPackage.packagePath,
+                        apexPackage.packageName)) {
+                    success = false;
+                    break;
                 }
             }
         }
+
         if (success) {
             session.setStagedSessionReady();
         } else {
@@ -206,15 +238,59 @@
         }
     }
 
-    void abortSession(@NonNull PackageInstallerSession sessionInfo) {
-        updateStoredSession(sessionInfo);
+    void abortSession(@NonNull PackageInstallerSession session) {
         synchronized (mStagedSessions) {
-            mStagedSessions.remove(sessionInfo.sessionId);
+            updateStoredSession(session);
+            mStagedSessions.remove(session.sessionId);
         }
     }
 
+    @GuardedBy("mStagedSessions")
+    private boolean isMultiPackageSessionComplete(@NonNull PackageInstallerSession session) {
+        // This method assumes that the argument is either a parent session of a multi-package
+        // i.e. isMultiPackage() returns true, or that it is a child session, i.e.
+        // hasParentSessionId() returns true.
+        if (session.isMultiPackage()) {
+            // Parent session of a multi-package group. Check that we restored all the children.
+            for (int childSession : session.getChildSessionIds()) {
+                if (mStagedSessions.get(childSession) == null) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        if (session.hasParentSessionId()) {
+            PackageInstallerSession parent = mStagedSessions.get(session.getParentSessionId());
+            if (parent == null) {
+                return false;
+            }
+            return isMultiPackageSessionComplete(parent);
+        }
+        Slog.wtf(TAG, "Attempting to restore an invalid multi-package session.");
+        return false;
+    }
+
     void restoreSession(@NonNull PackageInstallerSession session) {
-        updateStoredSession(session);
+        PackageInstallerSession sessionToResume = session;
+        synchronized (mStagedSessions) {
+            mStagedSessions.append(session.sessionId, session);
+            // For multi-package sessions, we don't know in which order they will be restored. We
+            // need to wait until we have restored all the session in a group before restoring them.
+            if (session.isMultiPackage() || session.hasParentSessionId()) {
+                if (!isMultiPackageSessionComplete(session)) {
+                    // Still haven't recovered all sessions of the group, return.
+                    return;
+                }
+                // Group recovered, find the parent if necessary and resume the installation.
+                if (session.hasParentSessionId()) {
+                    sessionToResume = mStagedSessions.get(session.getParentSessionId());
+                }
+            }
+        }
+        checkStateAndResume(sessionToResume);
+    }
+
+    private void checkStateAndResume(@NonNull PackageInstallerSession session) {
         // Check the state of the session and decide what to do next.
         if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) {
             // Final states, nothing to do.
@@ -227,6 +303,8 @@
         } else {
             // Session had already being marked ready. Start the checks to verify if there is any
             // follow-up work.
+            // TODO(b/118865310): should this be synchronous to ensure it completes before
+            //                    systemReady() finishes?
             mBgHandler.post(() -> resumeSession(session));
         }
     }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 48ddf8c..9df0f72 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -319,8 +319,14 @@
         PackageManager pm = context.getPackageManager();
         try {
             PackageInstaller packageInstaller = pm.getPackageInstaller();
+            String installerPackageName = pm.getInstallerPackageName(targetPackageName);
+            if (installerPackageName == null) {
+                sendFailure(statusReceiver, "Cannot find installer package");
+                return;
+            }
             PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
                     PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+            parentParams.setInstallerPackageName(installerPackageName);
             parentParams.setAllowDowngrade(true);
             parentParams.setMultiPackage();
             int parentSessionId = packageInstaller.createSession(parentParams);
@@ -329,6 +335,7 @@
             for (PackageRollbackInfo info : data.packages) {
                 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                         PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+                params.setInstallerPackageName(installerPackageName);
                 params.setAllowDowngrade(true);
                 int sessionId = packageInstaller.createSession(params);
                 PackageInstaller.Session session = packageInstaller.openSession(sessionId);
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4e71a05..40664fe 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -96,10 +96,10 @@
 import com.android.internal.os.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
 import com.android.internal.os.KernelCpuThreadReader;
-import com.android.internal.os.KernelUidCpuActiveTimeReader;
-import com.android.internal.os.KernelUidCpuClusterTimeReader;
-import com.android.internal.os.KernelUidCpuFreqTimeReader;
-import com.android.internal.os.KernelUidCpuTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
+import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
 import com.android.internal.os.KernelWakelockReader;
 import com.android.internal.os.KernelWakelockStats;
 import com.android.internal.os.LooperStats;
@@ -231,14 +231,16 @@
     private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
     private final CompanionHandler mHandler;
 
-    private KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
+    // Disables throttler on CPU time readers.
+    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
+            new KernelCpuUidUserSysTimeReader(false);
     private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
-    private KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
-            new KernelUidCpuFreqTimeReader();
-    private KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
-            new KernelUidCpuActiveTimeReader();
-    private KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
-            new KernelUidCpuClusterTimeReader();
+    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
+            new KernelCpuUidFreqTimeReader(false);
+    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
+            new KernelCpuUidActiveTimeReader(false);
+    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
+            new KernelCpuUidClusterTimeReader(false);
     private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
             new StoragedUidIoStatsReader();
     @Nullable
@@ -294,12 +296,6 @@
                     numSpeedSteps);
             firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
         }
-        // use default throttling in
-        // frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
-        mKernelUidCpuFreqTimeReader.setThrottleInterval(0);
-        long[] freqs = mKernelUidCpuFreqTimeReader.readFreqs(powerProfile);
-        mKernelUidCpuClusterTimeReader.setThrottleInterval(0);
-        mKernelUidCpuActiveTimeReader.setThrottleInterval(0);
 
         // Enable push notifications of throttling from vendor thermal
         // management subsystem via thermalservice.
@@ -914,7 +910,8 @@
     private void pullKernelUidCpuTime(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        mKernelUidCpuTimeReader.readAbsolute((uid, userTimeUs, systemTimeUs) -> {
+        mCpuUidUserSysTimeReader.readAbsolute((uid, timesUs) -> {
+            long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
             e.writeInt(uid);
             e.writeLong(userTimeUs);
@@ -926,7 +923,7 @@
     private void pullKernelUidCpuFreqTime(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        mKernelUidCpuFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
+        mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
                 if (cpuFreqTimeMs[freqIndex] != 0) {
                     StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
@@ -943,7 +940,7 @@
     private void pullKernelUidCpuClusterTime(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        mKernelUidCpuClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
+        mCpuUidClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
             for (int i = 0; i < cpuClusterTimesMs.length; i++) {
                 StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
                         wallClockNanos);
@@ -958,7 +955,7 @@
     private void pullKernelUidCpuActiveTime(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        mKernelUidCpuActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
+        mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
             e.writeInt(uid);
             e.writeLong((long) cpuActiveTimesMs);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 7c1e619..8d2bab4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1219,13 +1219,13 @@
     }
 
     @Override
-    public void onNotificationExpansionChanged(String key, boolean userAction,
-            boolean expanded) throws RemoteException {
+    public void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded,
+            int location) throws RemoteException {
         enforceStatusBarService();
         long identity = Binder.clearCallingIdentity();
         try {
             mNotificationDelegate.onNotificationExpansionChanged(
-                    key, userAction, expanded);
+                    key, userAction, expanded, location);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 780eda49..711ca00 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1975,7 +1975,7 @@
         } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
             return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
         } else if (taskSwitch && allowTaskSnapshot) {
-            if (mWmService.mLowRamTaskSnapshots) {
+            if (mWmService.mLowRamTaskSnapshotsAndRecents) {
                 // For low RAM devices, we use the splash screen starting window instead of the
                 // task snapshot starting window.
                 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 01a5622..beb3d82 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static com.android.server.wm.TaskSnapshotPersister.DISABLE_FULL_SIZED_BITMAPS;
-import static com.android.server.wm.TaskSnapshotPersister.REDUCED_SCALE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -90,9 +89,8 @@
     private final WindowManagerService mService;
 
     private final TaskSnapshotCache mCache;
-    private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister(
-            Environment::getDataSystemCeDirectory);
-    private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister);
+    private final TaskSnapshotPersister mPersister;
+    private final TaskSnapshotLoader mLoader;
     private final ArraySet<Task> mSkipClosingAppSnapshotTasks = new ArraySet<>();
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
     private final Handler mHandler = new Handler();
@@ -116,6 +114,8 @@
 
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
+        mPersister = new TaskSnapshotPersister(mService, Environment::getDataSystemCeDirectory);
+        mLoader = new TaskSnapshotLoader(mPersister);
         mCache = new TaskSnapshotCache(mService, mLoader);
         mIsRunningOnTv = mService.mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_LEANBACK);
@@ -270,7 +270,7 @@
         }
 
         final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
-        final float scaleFraction = isLowRamDevice ? REDUCED_SCALE : 1f;
+        final float scaleFraction = isLowRamDevice ? mPersister.getReducedScale() : 1f;
         task.getBounds(mTmpRect);
         mTmpRect.offsetTo(0, 0);
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 0e1570b..d30843b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.TaskSnapshotPersister.*;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -92,7 +91,7 @@
                     proto.topActivityComponent);
             return new TaskSnapshot(topActivityComponent, buffer, proto.orientation,
                     new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
-                    reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
+                    reducedResolution, reducedResolution ? mPersister.getReducedScale() : 1f,
                     proto.isRealSnapshot, proto.windowingMode, proto.systemUiVisibility,
                     proto.isTranslucent);
         } catch (IOException e) {
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 24b5b61..e6d646c 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -52,7 +52,9 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotPersister" : TAG_WM;
     private static final String SNAPSHOTS_DIRNAME = "snapshots";
     private static final String REDUCED_POSTFIX = "_reduced";
-    static final float REDUCED_SCALE = ActivityManager.isLowRamDeviceStatic() ? 0.6f : 0.5f;
+    private static final float REDUCED_SCALE = .5f;
+    private static final float LOW_RAM_REDUCED_SCALE = .6f;
+    private static final float LOW_RAM_RECENTS_REDUCED_SCALE = .1f;
     static final boolean DISABLE_FULL_SIZED_BITMAPS = ActivityManager.isLowRamDeviceStatic();
     private static final long DELAY_MS = 100;
     private static final int QUALITY = 95;
@@ -71,6 +73,7 @@
     private boolean mStarted;
     private final Object mLock = new Object();
     private final DirectoryResolver mDirectoryResolver;
+    private final float mReducedScale;
 
     /**
      * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -79,8 +82,16 @@
     @GuardedBy("mLock")
     private final ArraySet<Integer> mPersistedTaskIdsSinceLastRemoveObsolete = new ArraySet<>();
 
-    TaskSnapshotPersister(DirectoryResolver resolver) {
+    TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
         mDirectoryResolver = resolver;
+        if (service.mLowRamTaskSnapshotsAndRecents) {
+            // Use very low res snapshots if we are using Go version of recents.
+            mReducedScale = LOW_RAM_RECENTS_REDUCED_SCALE;
+        } else {
+            // TODO(122671846) Replace the low RAM value scale with the above when it is fully built
+            mReducedScale = ActivityManager.isLowRamDeviceStatic()
+                    ? LOW_RAM_REDUCED_SCALE : REDUCED_SCALE;
+        }
     }
 
     /**
@@ -144,6 +155,15 @@
         }
     }
 
+    /**
+     * Gets the scaling the persister uses for low resolution task snapshots.
+     *
+     * @return the reduced scale of task snapshots when they are set to be low res
+     */
+    float getReducedScale() {
+        return mReducedScale;
+    }
+
     @TestApi
     void waitForQueueEmpty() {
         while (true) {
@@ -350,8 +370,8 @@
             final Bitmap reduced = mSnapshot.isReducedResolution()
                     ? swBitmap
                     : Bitmap.createScaledBitmap(swBitmap,
-                            (int) (bitmap.getWidth() * REDUCED_SCALE),
-                            (int) (bitmap.getHeight() * REDUCED_SCALE), true /* filter */);
+                            (int) (bitmap.getWidth() * mReducedScale),
+                            (int) (bitmap.getHeight() * mReducedScale), true /* filter */);
             try {
                 FileOutputStream reducedFos = new FileOutputStream(reducedFile);
                 reduced.compress(JPEG, QUALITY, reducedFos);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fda7a85..efb38f5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -433,11 +433,12 @@
     final long mDrawLockTimeoutMillis;
     final boolean mAllowAnimationsInLowPowerMode;
 
+    // TODO(b/122671846) Remove the flag below in favor of isLowRam once feature is stable
     /**
      * Use very low resolution task snapshots. Replaces task snapshot starting windows with
      * splashscreen starting windows. Used on low RAM devices to save memory.
      */
-    final boolean mLowRamTaskSnapshots;
+    final boolean mLowRamTaskSnapshotsAndRecents;
 
     final boolean mAllowBootMessages;
 
@@ -955,7 +956,7 @@
                 com.android.internal.R.bool.config_disableTransitionAnimation);
         mPerDisplayFocusEnabled = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_perDisplayFocusEnabled);
-        mLowRamTaskSnapshots = context.getResources().getBoolean(
+        mLowRamTaskSnapshotsAndRecents = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
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 3a6cdc2..a89198a 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -147,12 +147,12 @@
                 }
 
                 @Override
-                void writeStringSetting(String key, String value) {
+                void writeStringSystemProperty(String key, String value) {
                     // do nothing
                 }
 
                 @Override
-                boolean readBooleanSetting(String key, boolean defVal) {
+                boolean readBooleanSystemProperty(String key, boolean defVal) {
                     switch (key) {
                         case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE:
                             return mMutingEnabled;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
new file mode 100644
index 0000000..73e9613
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -0,0 +1,305 @@
+/*
+ * 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.pm;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.content.pm.PackageInstaller;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.FastXmlSerializer;
+
+import libcore.io.IoUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class PackageInstallerSessionTest {
+    private File mTmpDir;
+    private AtomicFile mSessionsFile;
+    private static final String TAG_SESSIONS = "sessions";
+
+    @Mock
+    PackageManagerService mMockPackageManagerInternal;
+
+    @Before
+    public void setUp() throws Exception {
+        mTmpDir = IoUtils.createTemporaryDirectory("PackageInstallerSessionTest");
+        mSessionsFile = new AtomicFile(
+                new File(mTmpDir.getAbsolutePath() + "/sessions.xml"), "package-session");
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testWriteAndRestoreSessionXmlSimpleSession() {
+        PackageInstallerSession session = createSimpleSession();
+        dumpSession(session);
+        List<PackageInstallerSession> restored = restoreSessions();
+        assertEquals(1, restored.size());
+        assertSessionsEquivalent(session, restored.get(0));
+    }
+
+    @Test
+    public void testWriteAndRestoreSessionXmlStagedSession() {
+        PackageInstallerSession session = createStagedSession();
+        dumpSession(session);
+        List<PackageInstallerSession> restored = restoreSessions();
+        assertEquals(1, restored.size());
+        assertSessionsEquivalent(session, restored.get(0));
+    }
+
+    @Test
+    public void testWriteAndRestoreSessionXmlGrantedPermission() {
+        PackageInstallerSession session = createSessionWithGrantedPermissions();
+        dumpSession(session);
+        List<PackageInstallerSession> restored = restoreSessions();
+        assertEquals(1, restored.size());
+        assertSessionsEquivalent(session, restored.get(0));
+    }
+
+    @Test
+    public void testWriteAndRestoreSessionXmlMultiPackageSessions() {
+        PackageInstallerSession session = createMultiPackageParentSession(123, new int[]{234, 345});
+        PackageInstallerSession childSession1 = createMultiPackageChildSession(234, 123);
+        PackageInstallerSession childSession2 = createMultiPackageChildSession(345, 123);
+        List<PackageInstallerSession> sessionGroup =
+                Arrays.asList(session, childSession1, childSession2);
+        dumpSessions(sessionGroup);
+        List<PackageInstallerSession> restored = restoreSessions();
+        assertEquals(3, restored.size());
+        assertSessionsEquivalent(sessionGroup, restored);
+    }
+
+    private PackageInstallerSession createSimpleSession() {
+        return createSession(false, false, 123, false, PackageInstaller.SessionInfo.INVALID_ID,
+                null);
+    }
+
+    private PackageInstallerSession createStagedSession() {
+        return createSession(true, false, 123, false, PackageInstaller.SessionInfo.INVALID_ID,
+                null);
+    }
+
+    private PackageInstallerSession createSessionWithGrantedPermissions() {
+        return createSession(false, true, 123, false, PackageInstaller.SessionInfo.INVALID_ID,
+                null);
+    }
+
+    private PackageInstallerSession createMultiPackageParentSession(int sessionId,
+                                                                    int[] childSessionIds) {
+        return createSession(false, false, sessionId, true,
+                PackageInstaller.SessionInfo.INVALID_ID, childSessionIds);
+    }
+
+    private PackageInstallerSession createMultiPackageChildSession(int sessionId,
+                                                                   int parentSessionId) {
+        return createSession(false, false, sessionId, false, parentSessionId, null);
+    }
+
+    private PackageInstallerSession createSession(boolean staged, boolean withGrantedPermissions,
+                                                  int sessionId, boolean isMultiPackage,
+                                                  int parentSessionId, int[] childSessionIds) {
+        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+        if (staged) {
+            params.isStaged = true;
+        }
+        if (withGrantedPermissions) {
+            params.grantedRuntimePermissions = new String[]{"permission1", "permission2"};
+        }
+        if (isMultiPackage) {
+            params.isMultiPackage = true;
+        }
+        return new PackageInstallerSession(
+                /* callback */ null,
+                /* context */null,
+                /* pm */ mMockPackageManagerInternal,
+                /* sessionProvider */ null,
+                /* looper */ BackgroundThread.getHandler().getLooper(),
+                /* stagingManager */ null,
+                /* sessionId */ sessionId,
+                /* userId */  456,
+                /* installerPackageName */ "testInstaller",
+                /* installerUid */ -1,
+                /* sessionParams */ params,
+                /* createdMillis */ 0L,
+                /* stageDir */ mTmpDir,
+                /* stageCid */ null,
+                /* prepared */ true,
+                /* sealed */ false,  // Setting to true would trigger some PM logic.
+                /* childSessionIds */ childSessionIds != null ? childSessionIds : new int[0],
+                /* parentSessionId */ parentSessionId,
+                /* isReady */ staged ? true : false,
+                /* isFailed */ false,
+                /* isApplied */false,
+                /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.VERIFICATION_FAILED);
+    }
+
+    private void dumpSession(PackageInstallerSession session) {
+        dumpSessions(Arrays.asList(session));
+    }
+
+    private void dumpSessions(List<PackageInstallerSession> sessions) {
+        FileOutputStream fos = null;
+        try {
+            fos = mSessionsFile.startWrite();
+
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, TAG_SESSIONS);
+            for (PackageInstallerSession session : sessions) {
+                session.write(out, mTmpDir);
+            }
+            out.endTag(null, TAG_SESSIONS);
+            out.endDocument();
+
+            mSessionsFile.finishWrite(fos);
+            Slog.d("PackageInstallerSessionTest", new String(mSessionsFile.readFully()));
+        } catch (IOException e) {
+            if (fos != null) {
+                mSessionsFile.failWrite(fos);
+            }
+        }
+    }
+
+    // This is roughly the logic used in PackageInstallerService to read the session. Note that
+    // this test stresses readFromXml method from PackageInstallerSession, and doesn't cover the
+    // PackageInstallerService portion of the parsing.
+    private List<PackageInstallerSession> restoreSessions() {
+        List<PackageInstallerSession> ret = new ArrayList<>();
+        FileInputStream fis = null;
+        try {
+            fis = mSessionsFile.openRead();
+            final XmlPullParser in = Xml.newPullParser();
+            in.setInput(fis, StandardCharsets.UTF_8.name());
+
+            int type;
+            while ((type = in.next()) != END_DOCUMENT) {
+                if (type == START_TAG) {
+                    final String tag = in.getName();
+                    if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
+                        final PackageInstallerSession session;
+                        try {
+                            session = PackageInstallerSession.readFromXml(in, null,
+                                    null, mMockPackageManagerInternal,
+                                    BackgroundThread.getHandler().getLooper(), null,
+                                    mTmpDir, null);
+                            ret.add(session);
+                        } catch (Exception e) {
+                            Slog.e("PackageInstallerSessionTest", "Exception ", e);
+                            continue;
+                        }
+                    }
+                }
+            }
+        } catch (FileNotFoundException e) {
+            // Missing sessions are okay, probably first boot
+        } catch (IOException | XmlPullParserException e) {
+
+        } finally {
+            IoUtils.closeQuietly(fis);
+        }
+        return ret;
+    }
+
+    private void assertSessionParamsEquivalent(PackageInstaller.SessionParams expected,
+                                               PackageInstaller.SessionParams actual) {
+        assertEquals(expected.mode, actual.mode);
+        assertEquals(expected.installFlags, actual.installFlags);
+        assertEquals(expected.installLocation, actual.installLocation);
+        assertEquals(expected.installReason, actual.installReason);
+        assertEquals(expected.sizeBytes, actual.sizeBytes);
+        assertEquals(expected.appPackageName, actual.appPackageName);
+        assertEquals(expected.appIcon, actual.appIcon);
+        assertEquals(expected.originatingUri, actual.originatingUri);
+        assertEquals(expected.originatingUid, actual.originatingUid);
+        assertEquals(expected.referrerUri, actual.referrerUri);
+        assertEquals(expected.abiOverride, actual.abiOverride);
+        assertEquals(expected.volumeUuid, actual.volumeUuid);
+        assertArrayEquals(expected.grantedRuntimePermissions, actual.grantedRuntimePermissions);
+        assertEquals(expected.installerPackageName, actual.installerPackageName);
+        assertEquals(expected.isMultiPackage, actual.isMultiPackage);
+        assertEquals(expected.isStaged, actual.isStaged);
+    }
+
+    private void assertSessionsEquivalent(List<PackageInstallerSession> expected,
+                                          List<PackageInstallerSession> actual) {
+        assertEquals(expected.size(), actual.size());
+        for (PackageInstallerSession expectedSession : expected) {
+            boolean foundSession = false;
+            for (PackageInstallerSession actualSession : actual) {
+                if (expectedSession.sessionId == actualSession.sessionId) {
+                    // We should only encounter each expected session once.
+                    assertFalse(foundSession);
+                    foundSession = true;
+                    assertSessionsEquivalent(expectedSession, actualSession);
+                }
+            }
+            assertTrue(foundSession);
+        }
+    }
+
+    private void assertSessionsEquivalent(PackageInstallerSession expected,
+                                          PackageInstallerSession actual) {
+        assertEquals(expected.sessionId, actual.sessionId);
+        assertEquals(expected.userId, actual.userId);
+        assertSessionParamsEquivalent(expected.params, actual.params);
+        assertEquals(expected.getInstallerUid(), actual.getInstallerUid());
+        assertEquals(expected.stageDir.getAbsolutePath(), actual.stageDir.getAbsolutePath());
+        assertEquals(expected.stageCid, actual.stageCid);
+        assertEquals(expected.isPrepared(), actual.isPrepared());
+        assertEquals(expected.isStaged(), actual.isStaged());
+        assertEquals(expected.isStagedSessionApplied(), actual.isStagedSessionApplied());
+        assertEquals(expected.isStagedSessionFailed(), actual.isStagedSessionFailed());
+        assertEquals(expected.isStagedSessionReady(), actual.isStagedSessionReady());
+        assertEquals(expected.getStagedSessionErrorCode(), actual.getStagedSessionErrorCode());
+        assertEquals(expected.isPrepared(), actual.isPrepared());
+        assertEquals(expected.isSealed(), actual.isSealed());
+        assertEquals(expected.isMultiPackage(), actual.isMultiPackage());
+        assertEquals(expected.hasParentSessionId(), actual.hasParentSessionId());
+        assertEquals(expected.getParentSessionId(), actual.getParentSessionId());
+        assertArrayEquals(expected.getChildSessionIds(), actual.getChildSessionIds());
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 94b21af..c0f9b80 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -185,6 +185,9 @@
 
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
             TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
+
+    private static final int NOTIFICATION_LOCATION_UNKNOWN = 0;
+
     @Mock
     private NotificationListeners mListeners;
     @Mock private NotificationAssistants mAssistants;
@@ -2528,11 +2531,13 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, true,
+                NOTIFICATION_LOCATION_UNKNOWN);
         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((true)));
         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), true, false,
+                NOTIFICATION_LOCATION_UNKNOWN);
         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(true), eq((false)));
         assertTrue(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
     }
@@ -2542,11 +2547,13 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
+                NOTIFICATION_LOCATION_UNKNOWN);
         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
         verify(mAssistants).notifyAssistantExpansionChangedLocked(eq(r.sbn), eq(false), eq((true)));
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, false,
+                NOTIFICATION_LOCATION_UNKNOWN);
         assertFalse(mService.getNotificationRecord(r.getKey()).getStats().hasExpanded());
         verify(mAssistants).notifyAssistantExpansionChangedLocked(
                 eq(r.sbn), eq(false), eq((false)));
@@ -3793,7 +3800,8 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
+                NOTIFICATION_LOCATION_UNKNOWN);
         NotificationVisibility[] notificationVisibility = new NotificationVisibility[] {
                 NotificationVisibility.obtain(r.getKey(), 0, 0, true)
         };
@@ -3808,7 +3816,8 @@
         NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
 
-        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true);
+        mService.mNotificationDelegate.onNotificationExpansionChanged(r.getKey(), false, true,
+                NOTIFICATION_LOCATION_UNKNOWN);
 
         assertEquals(0, mService.countLogSmartSuggestionsVisible);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 946ffb60..d29e3fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -53,7 +53,7 @@
     public void setUp() {
         final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
         mTestUserId = um.getUserHandle();
-        mPersister = new TaskSnapshotPersister(userId -> FILES_DIR);
+        mPersister = new TaskSnapshotPersister(mWm, userId -> FILES_DIR);
         mLoader = new TaskSnapshotLoader(mPersister);
         mPersister.start();
     }
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 26ec6de..85c53f2 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -42,7 +42,7 @@
 
     // This series of errors as specified by the standards
     // specified in ril.h
-    /** Operator determined barring. */
+    /** Operator determined barring. (no retry) */
     public static final int OPERATOR_BARRED = 0x08;
     /** NAS signalling. */
     public static final int NAS_SIGNALLING = 0x0E;
@@ -91,6 +91,11 @@
     public static final int FILTER_SYTAX_ERROR = 0x2D;
     /** Packet Data Protocol (PDP) without active traffic flow template (TFT). */
     public static final int PDP_WITHOUT_ACTIVE_TFT = 0x2E;
+    /**
+     * UE requested to modify QoS parameters or the bearer control mode, which is not compatible
+     * with the selected bearer control mode.
+     */
+    public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 0x30;
     /** Packet Data Protocol (PDP) type IPv4 only allowed. */
     public static final int ONLY_IPV4_ALLOWED = 0x32;                /* no retry */
     /** Packet Data Protocol (PDP) type IPv6 only allowed. */
@@ -103,6 +108,27 @@
     public static final int PDN_CONN_DOES_NOT_EXIST = 0x36;
     /** Multiple connections to a same PDN is not allowed. */
     public static final int MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 0x37;
+    /**
+     * Network has already initiated the activation, modification, or deactivation of bearer
+     * resources that was requested by the UE.
+     */
+    public static final int COLLISION_WITH_NETWORK_INITIATED_REQUEST = 0x38;
+    /**
+     * Network supports IPv4v6 PDP type only. Non-IP type is not allowed. In LTE mode of operation,
+     * this is a PDN throttling cause code, meaning the UE may throttle further requests to the
+     * same APN.
+     */
+    public static final int ONLY_IPV4V6_ALLOWED = 0x39;
+    /**
+     * Network supports non-IP PDP type only. IPv4, IPv6 and IPv4v6 is not allowed. In LTE mode of
+     * operation, this is a PDN throttling cause code, meaning the UE can throttle further requests
+     * to the same APN.
+     */
+    public static final int ONLY_NON_IP_ALLOWED = 0x3A;
+    /** QCI (QoS Class Identifier) indicated in the UE request cannot be supported. */
+    public static final int UNSUPPORTED_QCI_VALUE = 0x3B;
+    /** Procedure requested by the UE was rejected because the bearer handling is not supported. */
+    public static final int BEARER_HANDLING_NOT_SUPPORTED = 0x3C;
     /** Max number of Packet Data Protocol (PDP) context reached. */
     public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 0x41;
     /** Unsupported APN in current public land mobile network (PLMN). */
@@ -146,6 +172,742 @@
     public static final int EMM_ACCESS_BARRED_INFINITE_RETRY = 0x79;
     /** Authentication failure on emergency call. */
     public static final int AUTH_FAILURE_ON_EMERGENCY_CALL = 0x7A;
+    /** Not receiving a DNS address that was mandatory. */
+    public static final int INVALID_DNS_ADDR = 0x7B;
+    /** Not receiving either a PCSCF or a DNS address, one of them being mandatory. */
+    public static final int INVALID_PCSCF_OR_DNS_ADDRESS = 0x7C;
+    /** Emergency call bring up on a different ePDG. */
+    public static final int CALL_PREEMPT_BY_EMERGENCY_APN = 0x7F;
+    /** UE performs a detach or disconnect PDN action based on TE requirements. */
+    public static final int UE_INITIATED_DETACH_OR_DISCONNECT = 0x80;
+
+    /** Reason unspecified for foreign agent rejected MIP (Mobile IP) registration. */
+    public static final int MIP_FA_REASON_UNSPECIFIED = 0x7D0;
+    /** Foreign agent administratively prohibited MIP (Mobile IP) registration. */
+    public static final int MIP_FA_ADMIN_PROHIBITED = 0x7D1;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of insufficient resources. */
+    public static final int MIP_FA_INSUFFICIENT_RESOURCES = 0x7D2;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of MN-AAA authenticator was
+     * wrong.
+     */
+    public static final int MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 0x7D3;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of home agent authentication
+     * failure.
+     */
+    public static final int MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 0x7D4;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of requested lifetime was too
+     * long.
+     */
+    public static final int MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 0x7D5;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of malformed request. */
+    public static final int MIP_FA_MALFORMED_REQUEST = 0x7D6;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of malformed reply. */
+    public static final int MIP_FA_MALFORMED_REPLY = 0x7D7;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of requested encapsulation was
+     * unavailable.
+     */
+    public static final int MIP_FA_ENCAPSULATION_UNAVAILABLE = 0x7D8;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration of VJ Header Compression was
+     * unavailable.
+     */
+    public static final int MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 0x7D9;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of reverse tunnel was
+     * unavailable.
+     */
+    public static final int MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 0x7DA;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of reverse tunnel was mandatory
+     * but not requested by device.
+     */
+    public static final int MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 0x7DB;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of delivery style was not
+     * supported.
+     */
+    public static final int MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 0x7DC;
+    /**
+     * Foreign agent rejected MIP (Mobile IP) registration because of missing NAI (Network Access
+     * Identifier).
+     */
+    public static final int MIP_FA_MISSING_NAI = 0x7DD;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of missing Home Agent. */
+    public static final int MIP_FA_MISSING_HOME_AGENT = 0x7DE;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of missing Home Address. */
+    public static final int MIP_FA_MISSING_HOME_ADDRESS = 0x7DF;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of unknown challenge. */
+    public static final int MIP_FA_UNKNOWN_CHALLENGE = 0x7E0;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of missing challenge. */
+    public static final int MIP_FA_MISSING_CHALLENGE = 0x7E1;
+    /** Foreign agent rejected MIP (Mobile IP) registration because of stale challenge. */
+    public static final int MIP_FA_STALE_CHALLENGE = 0x7E2;
+    /** Reason unspecified for home agent rejected MIP (Mobile IP) registration. */
+    public static final int MIP_HA_REASON_UNSPECIFIED = 0x7E3;
+    /** Home agent administratively prohibited MIP (Mobile IP) registration. */
+    public static final int MIP_HA_ADMIN_PROHIBITED = 0x7E4;
+    /** Home agent rejected MIP (Mobile IP) registration because of insufficient resources. */
+    public static final int MIP_HA_INSUFFICIENT_RESOURCES = 0x7E5;
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of MN-HA authenticator was
+     * wrong.
+     */
+    public static final int MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 0x7E6;
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of foreign agent authentication
+     * failure.
+     */
+    public static final int MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 0x7E7;
+    /** Home agent rejected MIP (Mobile IP) registration because of registration id mismatch. */
+    public static final int MIP_HA_REGISTRATION_ID_MISMATCH = 0x7E8;
+    /** Home agent rejected MIP (Mobile IP) registration because of malformed request. */
+    public static final int MIP_HA_MALFORMED_REQUEST = 0x7E9;
+    /** Home agent rejected MIP (Mobile IP) registration because of unknown home agent address. */
+    public static final int MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 0x7EA;
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of reverse tunnel was
+     * unavailable.
+     */
+    public static final int MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 0x7EB;
+    /**
+     * Home agent rejected MIP (Mobile IP) registration because of reverse tunnel is mandatory but
+     * not requested by device.
+     */
+    public static final int MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 0x7EC;
+    /** Home agent rejected MIP (Mobile IP) registration because of encapsulation unavailable. */
+    public static final int MIP_HA_ENCAPSULATION_UNAVAILABLE = 0x7ED;
+    /** Tearing down is in progress. */
+    public static final int CLOSE_IN_PROGRESS = 0x7EE;
+    /** Brought down by the network. */
+    public static final int NETWORK_INITIATED_TERMINATION = 0x7EF;
+    /** Another application in modem preempts the data call. */
+    public static final int MODEM_APP_PREEMPTED = 0x7F0;
+    /**
+     * IPV4 PDN is in throttled state due to network providing only IPV6 address during the
+     * previous VSNCP bringup (subs_limited_to_v6).
+     */
+    public static final int PDN_IPV4_CALL_DISALLOWED = 0x7F1;
+    /** IPV4 PDN is in throttled state due to previous VSNCP bringup failure(s). */
+    public static final int PDN_IPV4_CALL_THROTTLED = 0x7F2;
+    /**
+     * IPV6 PDN is in throttled state due to network providing only IPV4 address during the
+     * previous VSNCP bringup (subs_limited_to_v4).
+     */
+    public static final int PDN_IPV6_CALL_DISALLOWED = 0x7F3;
+    /** IPV6 PDN is in throttled state due to previous VSNCP bringup failure(s). */
+    public static final int PDN_IPV6_CALL_THROTTLED = 0x7F4;
+    /** Modem restart. */
+    public static final int MODEM_RESTART = 0x7F5;
+    /** PDP PPP calls are not supported. */
+    public static final int PDP_PPP_NOT_SUPPORTED = 0x7F6;
+    /** RAT on which the data call is attempted/connected is no longer the preferred RAT. */
+    public static final int UNPREFERRED_RAT = 0x7F7;
+    /** Physical link is in the process of cleanup. */
+    public static final int PHYSICAL_LINK_CLOSE_IN_PROGRESS = 0x7F8;
+    /** Interface bring up is attempted for an APN that is yet to be handed over to target RAT. */
+    public static final int APN_PENDING_HANDOVER = 0x7F9;
+    /** APN bearer type in the profile does not match preferred network mode. */
+    public static final int PROFILE_BEARER_INCOMPATIBLE = 0x7FA;
+    /** Card was refreshed or removed. */
+    public static final int SIM_CARD_CHANGED = 0x7FB;
+    /** Device is going into lower power mode or powering down. */
+    public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 0x7FC;
+    /** APN has been disabled. */
+    public static final int APN_DISABLED = 0x7FD;
+    /** Maximum PPP inactivity timer expired. */
+    public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 0x7FE;
+    /** IPv6 address transfer failed. */
+    public static final int IPV6_ADDRESS_TRANSFER_FAILED = 0x7FF;
+    /** Target RAT swap failed. */
+    public static final int TRAT_SWAP_FAILED = 0x800;
+    /** Device falls back from eHRPD to HRPD. */
+    public static final int EHRPD_TO_HRPD_FALLBACK = 0x801;
+    /**
+     * UE is in MIP-only configuration but the MIP configuration fails on call bring up due to
+     * incorrect provisioning.
+     */
+    public static final int MIP_CONFIG_FAILURE = 0x802;
+    /**
+     * PDN inactivity timer expired due to no data transmission in a configurable duration of time.
+     */
+    public static final int PDN_INACTIVITY_TIMER_EXPIRED = 0x803;
+    /**
+     * IPv4 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv4 data connections.
+     */
+    public static final int MAX_IPV4_CONNECTIONS = 0x804;
+    /**
+     * IPv6 data call bring up is rejected because the UE already maintains the allotted maximum
+     * number of IPv6 data connections.
+     */
+    public static final int MAX_IPV6_CONNECTIONS = 0x805;
+    /**
+     * New PDN bring up is rejected during interface selection because the UE has already allotted
+     * the available interfaces for other PDNs.
+     */
+    public static final int APN_MISMATCH = 0x806;
+    /**
+     * New call bring up is rejected since the existing data call IP type doesn't match the
+     * requested IP.
+     */
+    public static final int IP_VERSION_MISMATCH = 0x807;
+    /** Dial up networking (DUN) call bring up is rejected since UE is in eHRPD RAT. */
+    public static final int DUN_CALL_DISALLOWED = 0x808;
+    /*** Rejected/Brought down since UE is transition between EPC and NONEPC RAT. */
+    public static final int INTERNAL_EPC_NONEPC_TRANSITION = 0x809;
+    /** The current interface is being in use. */
+    public static final int INTERFACE_IN_USE = 0x80A;
+    /** PDN connection to the APN is disallowed on the roaming network. */
+    public static final int APN_DISALLOWED_ON_ROAMING = 0x80B;
+    /** APN-related parameters are changed. */
+    public static final int APN_PARAMETERS_CHANGED = 0x80C;
+    /** PDN is attempted to be brought up with NULL APN but NULL APN is not supported. */
+    public static final int NULL_APN_DISALLOWED = 0x80D;
+    /**
+     * Thermal level increases and causes calls to be torn down when normal mode of operation is
+     * not allowed.
+     */
+    public static final int THERMAL_MITIGATION = 0x80E;
+    /**
+     * PDN Connection to a given APN is disallowed because data is disabled from the device user
+     * interface settings.
+     */
+    public static final int DATA_SETTINGS_DISABLED = 0x80F;
+    /**
+     * PDN Connection to a given APN is disallowed because data roaming is disabled from the device
+     * user interface settings and the UE is roaming.
+     */
+    public static final int DATA_ROAMING_SETTINGS_DISABLED = 0x810;
+    /** DDS (Default data subscription) switch occurs. */
+    public static final int DDS_SWITCHED = 0x811;
+    /** PDN being brought up with an APN that is part of forbidden APN Name list. */
+    public static final int FORBIDDEN_APN_NAME = 0x812;
+    /** Default data subscription switch is in progress. */
+    public static final int DDS_SWITCH_IN_PROGRESS = 0x813;
+    /** Roaming is disallowed during call bring up. */
+    public static final int CALL_DISALLOWED_IN_ROAMING = 0x814;
+    /**
+     * UE is unable to bring up a non-IP data call because the device is not camped on a NB1 cell.
+     */
+    public static final int NON_IP_NOT_SUPPORTED = 0x815;
+    /** Non-IP PDN is in throttled state due to previous VSNCP bringup failure(s). */
+    public static final int PDN_NON_IP_CALL_THROTTLED = 0x816;
+    /** Non-IP PDN is in disallowed state due to the network providing only an IP address. */
+    public static final int PDN_NON_IP_CALL_DISALLOWED = 0x817;
+    /** Device in CDMA locked state. */
+    public static final int CDMA_LOCK = 0x818;
+    /** Received an intercept order from the base station. */
+    public static final int CDMA_INTERCEPT = 0x819;
+    /** Receiving a reorder from the base station. */
+    public static final int CDMA_REORDER = 0x81A;
+    /** Receiving a release from the base station with a SO (Service Option) Reject reason. */
+    public static final int CDMA_RELEASE_DUE_TO_SO_REJECTION = 0x81B;
+    /** Receiving an incoming call from the base station. */
+    public static final int CDMA_INCOMING_CALL = 0x81C;
+    /** Received an alert stop from the base station due to incoming only. */
+    public static final int CDMA_ALERT_STOP = 0x81D;
+    /**
+     * Channel acquisition failures. This indicates that device has failed acquiring all the
+     * channels in the PRL.
+     */
+    public static final int CHANNEL_ACQUISITION_FAILURE = 0x81E;
+    /** Maximum access probes transmitted. */
+    public static final int MAX_ACCESS_PROBE = 0x81F;
+    /** Concurrent service is not supported by base station. */
+    public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 0x820;
+    /** There was no response received from the base station. */
+    public static final int NO_RESPONSE_FROM_BASE_STATION = 0x821;
+    /** The base station rejecting the call. */
+    public static final int REJECTED_BY_BASE_STATION = 0x822;
+    /** The concurrent services requested were not compatible. */
+    public static final int CONCURRENT_SERVICES_INCOMPATIBLE = 0x823;
+    /** Device does not have CDMA service. */
+    public static final int NO_CDMA_SERVICE = 0x824;
+    /** RUIM not being present. */
+    public static final int RUIM_NOT_PRESENT = 0x825;
+    /** Receiving a retry order from the base station. */
+    public static final int CDMA_RETRY_ORDER = 0x826;
+    /** Access blocked by the base station. */
+    public static final int ACCESS_BLOCK = 0x827;
+    /** Access blocked by the base station for all mobile devices. */
+    public static final int ACCESS_BLOCK_ALL = 0x828;
+    /** Maximum access probes for the IS-707B call. */
+    public static final int IS707B_MAX_ACCESS_PROBES = 0x829;
+    /** Put device in thermal emergency. */
+    public static final int THERMAL_EMERGENCY = 0x82A;
+    /** In favor of a voice call or SMS when concurrent voice and data are not supported. */
+    public static final int CONCURRENT_SERVICES_NOT_ALLOWED = 0x82B;
+    /** The other clients rejected incoming call. */
+    public static final int INCOMING_CALL_REJECTED = 0x82C;
+    /** No service on the gateway. */
+    public static final int NO_SERVICE_ON_GATEWAY = 0x82D;
+    /** GPRS context is not available. */
+    public static final int NO_GPRS_CONTEXT = 0x82E;
+    /**
+     * Network refuses service to the MS because either an identity of the MS is not acceptable to
+     * the network or the MS does not pass the authentication check.
+     */
+    public static final int ILLEGAL_MS = 0x82F;
+    /** ME could not be authenticated and the ME used is not acceptable to the network. */
+    public static final int ILLEGAL_ME = 0x830;
+    /** Not allowed to operate either GPRS or non-GPRS services. */
+    public static final int GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 0x831;
+    /** MS is not allowed to operate GPRS services. */
+    public static final int GPRS_SERVICES_NOT_ALLOWED = 0x832;
+    /** No matching identity or context could be found in the network. */
+    public static final int MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 0x833;
+    /**
+     * Mobile reachable timer has expired, or the GMM context data related to the subscription does
+     * not exist in the SGSN.
+     */
+    public static final int IMPLICITLY_DETACHED = 0x834;
+    /**
+     * UE requests GPRS service, or the network initiates a detach request in a PLMN which does not
+     * offer roaming for GPRS services to that MS.
+     */
+    public static final int PLMN_NOT_ALLOWED = 0x835;
+    /**
+     * MS requests service, or the network initiates a detach request, in a location area where the
+     * HPLMN determines that the MS, by subscription, is not allowed to operate.
+     */
+    public static final int LOCATION_AREA_NOT_ALLOWED = 0x836;
+    /**
+     * UE requests GPRS service or the network initiates a detach request in a PLMN that does not
+     * offer roaming for GPRS services.
+     */
+    public static final int GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 0x837;
+    /** PDP context already exists. */
+    public static final int PDP_DUPLICATE = 0x838;
+    /** RAT change on the UE. */
+    public static final int UE_RAT_CHANGE = 0x839;
+    /** Network cannot serve a request from the MS due to congestion. */
+    public static final int CONGESTION = 0x83A;
+    /**
+     * MS requests an establishment of the radio access bearers for all active PDP contexts by
+     * sending a service request message indicating data to the network, but the SGSN does not have
+     * any active PDP context.
+     */
+    public static final int NO_PDP_CONTEXT_ACTIVATED = 0x83B;
+    /** Access class blocking restrictions for the current camped cell. */
+    public static final int ACCESS_CLASS_DSAC_REJECTION = 0x83C;
+    /** SM attempts PDP activation for a maximum of four attempts. */
+    public static final int PDP_ACTIVATE_MAX_RETRY_FAILED = 0x83D;
+    /** Radio access bearer failure. */
+    public static final int RADIO_ACCESS_BEARER_FAILURE = 0x83E;
+    /** Invalid EPS bearer identity in the request. */
+    public static final int ESM_UNKNOWN_EPS_BEARER_CONTEXT = 0x83F;
+    /** Data radio bearer is released by the RRC. */
+    public static final int DRB_RELEASED_BY_RRC = 0x840;
+    /** Indicate the connection was released. */
+    public static final int CONNECTION_RELEASED = 0x841;
+    /** UE is detached. */
+    public static final int EMM_DETACHED = 0x842;
+    /** Attach procedure is rejected by the network. */
+    public static final int EMM_ATTACH_FAILED = 0x843;
+    /** Attach procedure is started for EMC purposes. */
+    public static final int EMM_ATTACH_STARTED = 0x844;
+    /** Service request procedure failure. */
+    public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 0x845;
+    /** Active dedicated bearer was requested using the same default bearer ID. */
+    public static final int DUPLICATE_BEARER_ID = 0x846;
+    /** Collision scenarios for the UE and network-initiated procedures. */
+    public static final int ESM_COLLISION_SCENARIOS = 0x847;
+    /** Bearer must be deactivated to synchronize with the network. */
+    public static final int ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 0x848;
+    /** Active dedicated bearer was requested for an existing default bearer. */
+    public static final int ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 0x849;
+    /** Bad OTA message is received from the network. */
+    public static final int ESM_BAD_OTA_MESSAGE = 0x84A;
+    /** Download server rejected the call. */
+    public static final int ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 0x84B;
+    /** PDN was disconnected by the downlaod server due to IRAT. */
+    public static final int ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 0x84C;
+    /** Dedicated bearer will be deactivated regardless of the network response. */
+    public static final int DS_EXPLICIT_DEACTIVATION = 0x84D;
+    /** No specific local cause is mentioned, usually a valid OTA cause. */
+    public static final int ESM_LOCAL_CAUSE_NONE = 0x84E;
+    /** Throttling is not needed for this service request failure. */
+    public static final int LTE_THROTTLING_NOT_REQUIRED = 0x84F;
+    /** Access control list check failure at the lower layer. */
+    public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 0x850;
+    /** Service is not allowed on the requested PLMN. */
+    public static final int SERVICE_NOT_ALLOWED_ON_PLMN = 0x851;
+    /** T3417 timer expiration of the service request procedure. */
+    public static final int EMM_T3417_EXPIRED = 0x852;
+    /** Extended service request fails due to expiration of the T3417 EXT timer. */
+    public static final int EMM_T3417_EXT_EXPIRED = 0x853;
+    /** Transmission failure of radio resource control (RRC) uplink data. */
+    public static final int RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 0x854;
+    /** Radio resource control (RRC) uplink data delivery failed due to a handover. */
+    public static final int RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 0x855;
+    /** Radio resource control (RRC) uplink data delivery failed due to a connection release. */
+    public static final int RRC_UPLINK_CONNECTION_RELEASE = 0x856;
+    /** Radio resource control (RRC) uplink data delivery failed due to a radio link failure. */
+    public static final int RRC_UPLINK_RADIO_LINK_FAILURE = 0x857;
+    /**
+     * Radio resource control (RRC) is not connected but the non-access stratum (NAS) sends an
+     * uplink data request.
+     */
+    public static final int RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 0x858;
+    /** Radio resource control (RRC) connection failure at access stratum. */
+    public static final int RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 0x859;
+    /**
+     * Radio resource control (RRC) connection establishment is aborted due to another procedure.
+     */
+    public static final int RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 0x85A;
+    /** Radio resource control (RRC) connection establishment failed due to access barrred. */
+    public static final int RRC_CONNECTION_ACCESS_BARRED = 0x85B;
+    /**
+     * Radio resource control (RRC) connection establishment failed due to cell reselection at
+     * access stratum.
+     */
+    public static final int RRC_CONNECTION_CELL_RESELECTION = 0x85C;
+    /**
+     * Connection establishment failed due to configuration failure at the radio resource control
+     * (RRC).
+     */
+    public static final int RRC_CONNECTION_CONFIG_FAILURE = 0x85D;
+    /** Radio resource control (RRC) connection could not be established in the time limit. */
+    public static final int RRC_CONNECTION_TIMER_EXPIRED = 0x85E;
+    /**
+     * Connection establishment failed due to a link failure at the radio resource control (RRC).
+     */
+    public static final int RRC_CONNECTION_LINK_FAILURE = 0x85F;
+    /**
+     * Connection establishment failed as the radio resource control (RRC) is not camped on any
+     * cell.
+     */
+    public static final int RRC_CONNECTION_CELL_NOT_CAMPED = 0x860;
+    /**
+     * Connection establishment failed due to a service interval failure at the radio resource
+     * control (RRC).
+     */
+    public static final int RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 0x861;
+    /**
+     * Radio resource control (RRC) connection establishment failed due to the network rejecting
+     * the UE connection request.
+     */
+    public static final int RRC_CONNECTION_REJECT_BY_NETWORK = 0x862;
+    /** Normal radio resource control (RRC) connection release. */
+    public static final int RRC_CONNECTION_NORMAL_RELEASE = 0x863;
+    /**
+     * Radio resource control (RRC) connection release failed due to radio link failure conditions.
+     */
+    public static final int RRC_CONNECTION_RADIO_LINK_FAILURE = 0x864;
+    /** Radio resource control (RRC) connection re-establishment failure. */
+    public static final int RRC_CONNECTION_REESTABLISHMENT_FAILURE = 0x865;
+    /** UE is out of service during the call register. */
+    public static final int RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 0x866;
+    /**
+     * Connection has been released by the radio resource control (RRC) due to an abort request.
+     */
+    public static final int RRC_CONNECTION_ABORT_REQUEST = 0x867;
+    /**
+     * Radio resource control (RRC) connection released due to a system information block read
+     * error.
+     */
+    public static final int RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 0x868;
+    /** Network-initiated detach with reattach. */
+    public static final int NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 0x869;
+    /** Network-initiated detach without reattach. */
+    public static final int NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 0x86A;
+    /** ESM procedure maximum attempt timeout failure. */
+    public static final int ESM_PROCEDURE_TIME_OUT = 0x86B;
+    /**
+     * No PDP exists with the given connection ID while modifying or deactivating or activation for
+     * an already active PDP.
+     */
+    public static final int INVALID_CONNECTION_ID = 0x86C;
+    /** Maximum NSAPIs have been exceeded during PDP activation. */
+    public static final int MAXIMIUM_NSAPIS_EXCEEDED = 0x86D;
+    /** Primary context for NSAPI does not exist. */
+    public static final int INVALID_PRIMARY_NSAPI = 0x86E;
+    /** Unable to encode the OTA message for MT PDP or deactivate PDP. */
+    public static final int CANNOT_ENCODE_OTA_MESSAGE = 0x86F;
+    /**
+     * Radio access bearer is not established by the lower layers during activation, modification,
+     * or deactivation.
+     */
+    public static final int RADIO_ACCESS_BEARER_SETUP_FAILURE = 0x870;
+    /** Expiration of the PDP establish timer with a maximum of five retries. */
+    public static final int PDP_ESTABLISH_TIMEOUT_EXPIRED = 0x871;
+    /** Expiration of the PDP modify timer with a maximum of four retries. */
+    public static final int PDP_MODIFY_TIMEOUT_EXPIRED = 0x872;
+    /** Expiration of the PDP deactivate timer with a maximum of four retries. */
+    public static final int PDP_INACTIVE_TIMEOUT_EXPIRED = 0x873;
+    /** PDP activation failed due to RRC_ABORT or a forbidden PLMN. */
+    public static final int PDP_LOWERLAYER_ERROR = 0x874;
+    /** MO PDP modify collision when the MT PDP is already in progress. */
+    public static final int PDP_MODIFY_COLLISION = 0x875;
+    /** Maximum size of the L2 message was exceeded. */
+    public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 0x876;
+    /** Non-access stratum (NAS) request was rejected by the network. */
+    public static final int NAS_REQUEST_REJECTED_BY_NETWORK = 0x877;
+    /**
+     * Radio resource control (RRC) connection establishment failure due to an error in the request
+     * message.
+     */
+    public static final int RRC_CONNECTION_INVALID_REQUEST = 0x878;
+    /**
+     * Radio resource control (RRC) connection establishment failure due to a change in the
+     * tracking area ID.
+     */
+    public static final int RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 0x879;
+    /**
+     * Radio resource control (RRC) connection establishment failure due to the RF was unavailable.
+     */
+    public static final int RRC_CONNECTION_RF_UNAVAILABLE = 0x87A;
+    /**
+     * Radio resource control (RRC) connection was aborted before deactivating the LTE stack due to
+     * a successful LTE to WCDMA/GSM/TD-SCDMA IRAT change.
+     */
+    public static final int RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 0x87B;
+    /**
+     * If the UE has an LTE radio link failure before security is established, the radio resource
+     * control (RRC) connection must be released and the UE must return to idle.
+     */
+    public static final int RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 0x87C;
+    /**
+     * Radio resource control (RRC) connection was aborted by the non-access stratum (NAS) after an
+     * IRAT to LTE IRAT handover.
+     */
+    public static final int RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 0x87D;
+    /**
+     * Radio resource control (RRC) connection was aborted before deactivating the LTE stack after
+     * a successful LTE to GSM/EDGE IRAT cell change order procedure.
+     */
+    public static final int RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 0x87E;
+    /**
+     * Radio resource control (RRC) connection was aborted in the middle of a LTE to GSM IRAT cell
+     * change order procedure.
+     */
+    public static final int RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 0x87F;
+    /** IMSI present in the UE is unknown in the home subscriber server. */
+    public static final int IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 0x880;
+    /** IMEI of the UE is not accepted by the network. */
+    public static final int IMEI_NOT_ACCEPTED = 0x881;
+    /** EPS and non-EPS services are not allowed by the network. */
+    public static final int EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 0x882;
+    /** EPS services are not allowed in the PLMN. */
+    public static final int EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 0x883;
+    /** Mobile switching center is temporarily unreachable. */
+    public static final int MSC_TEMPORARILY_NOT_REACHABLE = 0x884;
+    /** CS domain is not available. */
+    public static final int CS_DOMAIN_NOT_AVAILABLE = 0x885;
+    /** ESM level failure. */
+    public static final int ESM_FAILURE = 0x886;
+    /** MAC level failure. */
+    public static final int MAC_FAILURE = 0x887;
+    /** Synchronization failure. */
+    public static final int SYNCHRONIZATION_FAILURE = 0x888;
+    /** UE security capabilities mismatch. */
+    public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 0x889;
+    /** Unspecified security mode reject. */
+    public static final int SECURITY_MODE_REJECTED = 0x88A;
+    /** Unacceptable non-EPS authentication. */
+    public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 0x88B;
+    /** CS fallback call establishment is not allowed. */
+    public static final int CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 0x88C;
+    /** No EPS bearer context was activated. */
+    public static final int NO_EPS_BEARER_CONTEXT_ACTIVATED = 0x88D;
+    /** Invalid EMM state. */
+    public static final int INVALID_EMM_STATE = 0x88E;
+    /** Non-Access Spectrum layer failure. */
+    public static final int NAS_LAYER_FAILURE = 0x88F;
+    /** Multiple PDP call feature is disabled. */
+    public static final int MULTIPLE_PDP_CALL_NOT_ALLOWED = 0x890;
+    /** Data call has been brought down because EMBMS is not enabled at the RRC layer. */
+    public static final int EMBMS_NOT_ENABLED = 0x891;
+    /** Data call was unsuccessfully transferred during the IRAT handover. */
+    public static final int IRAT_HANDOVER_FAILED = 0x892;
+    /** EMBMS data call has been successfully brought down. */
+    public static final int EMBMS_REGULAR_DEACTIVATION = 0x893;
+    /** Test loop-back data call has been successfully brought down. */
+    public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 0x894;
+    /** Lower layer registration failure. */
+    public static final int LOWER_LAYER_REGISTRATION_FAILURE = 0x895;
+    /**
+     * Network initiates a detach on LTE with error cause ""data plan has been replenished or has
+     * expired.
+     */
+    public static final int DATA_PLAN_EXPIRED = 0x896;
+    /** UMTS interface is brought down due to handover from UMTS to iWLAN. */
+    public static final int UMTS_HANDOVER_TO_IWLAN = 0x897;
+    /** Received a connection deny due to general or network busy on EVDO network. */
+    public static final int EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 0x898;
+    /** Received a connection deny due to billing or authentication failure on EVDO network. */
+    public static final int EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 0x899;
+    /** HDR system has been changed due to redirection or the PRL was not preferred. */
+    public static final int EVDO_HDR_CHANGED = 0x89A;
+    /** Device exited HDR due to redirection or the PRL was not preferred. */
+    public static final int EVDO_HDR_EXITED = 0x89B;
+    /** Device does not have an HDR session. */
+    public static final int EVDO_HDR_NO_SESSION = 0x89C;
+    /** It is ending an HDR call origination in favor of a GPS fix. */
+    public static final int EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 0x89D;
+    /** Connection setup on the HDR system was time out. */
+    public static final int EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 0x89E;
+    /** Device failed to acquire a co-located HDR for origination. */
+    public static final int FAILED_TO_ACQUIRE_COLOCATED_HDR = 0x89F;
+    /** OTASP commit is in progress. */
+    public static final int OTASP_COMMIT_IN_PROGRESS = 0x8A0;
+    /** Device has no hybrid HDR service. */
+    public static final int NO_HYBRID_HDR_SERVICE = 0x8A1;
+    /** HDR module could not be obtained because of the RF locked. */
+    public static final int HDR_NO_LOCK_GRANTED = 0x8A2;
+    /** DBM or SMS is in progress. */
+    public static final int DBM_OR_SMS_IN_PROGRESS = 0x8A3;
+    /** HDR module released the call due to fade. */
+    public static final int HDR_FADE = 0x8A4;
+    /** HDR system access failure. */
+    public static final int HDR_ACCESS_FAILURE = 0x8A5;
+    /**
+     * P_rev supported by 1 base station is less than 6, which is not supported for a 1X data call.
+     * The UE must be in the footprint of BS which has p_rev >= 6 to support this SO33 call.
+     */
+    public static final int UNSUPPORTED_1X_PREV = 0x8A6;
+    /** Client ended the data call. */
+    public static final int LOCAL_END = 0x8A7;
+    /** Device has no service. */
+    public static final int NO_SERVICE = 0x8A8;
+    /** Device lost the system due to fade. */
+    public static final int FADE = 0x8A9;
+    /** Receiving a release from the base station with no reason. */
+    public static final int NORMAL_RELEASE = 0x8AA;
+    /** Access attempt is already in progress. */
+    public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 0x8AB;
+    /** Device is in the process of redirecting or handing off to a different target system. */
+    public static final int REDIRECTION_OR_HANDOFF_IN_PROGRESS = 0x8AC;
+    /** Device is operating in Emergency mode. */
+    public static final int EMERGENCY_MODE = 0x8AD;
+    /** Device is in use (e.g., voice call). */
+    public static final int PHONE_IN_USE = 0x8AE;
+    /**
+     * Device operational mode is different from the mode requested in the traffic channel bring up.
+     */
+    public static final int INVALID_MODE = 0x8AF;
+    /** SIM was marked by the network as invalid for the circuit and/or packet service domain. */
+    public static final int INVALID_SIM_STATE = 0x8B0;
+    /** There is no co-located HDR. */
+    public static final int NO_COLLOCATED_HDR = 0x8B1;
+    /** UE is entering power save mode. */
+    public static final int UE_IS_ENTERING_POWERSAVE_MODE = 0x8B2;
+    /** Dual switch from single standby to dual standby is in progress. */
+    public static final int DUAL_SWITCH = 0x8B3;
+    /**
+     * Data call bring up fails in the PPP setup due to a timeout.
+     * (e.g., an LCP conf ack was not received from the network)
+     */
+    public static final int PPP_TIMEOUT = 0x8B4;
+    /**
+     * Data call bring up fails in the PPP setup due to an authorization failure.
+     * (e.g., authorization is required, but not negotiated with the network during an LCP phase)
+     */
+    public static final int PPP_AUTH_FAILURE = 0x8B5;
+    /** Data call bring up fails in the PPP setup due to an option mismatch. */
+    public static final int PPP_OPTION_MISMATCH = 0x8B6;
+    /** Data call bring up fails in the PPP setup due to a PAP failure. */
+    public static final int PPP_PAP_FAILURE = 0x8B7;
+    /** Data call bring up fails in the PPP setup due to a CHAP failure. */
+    public static final int PPP_CHAP_FAILURE = 0x8B8;
+    /**
+     * Data call bring up fails in the PPP setup because the PPP is in the process of cleaning the
+     * previous PPP session.
+     */
+    public static final int PPP_CLOSE_IN_PROGRESS = 0x8B9;
+    /**
+     * IPv6 interface bring up fails because the network provided only the IPv4 address for the
+     * upcoming PDN permanent client can reattempt a IPv6 call bring up after the IPv4 interface is
+     * also brought down. However, there is no guarantee that the network will provide a IPv6
+     * address.
+     */
+    public static final int LIMITED_TO_IPV4 = 0x8BA;
+    /**
+     * IPv4 interface bring up fails because the network provided only the IPv6 address for the
+     * upcoming PDN permanent client can reattempt a IPv4 call bring up after the IPv6 interface is
+     * also brought down. However there is no guarantee that the network will provide a IPv4
+     * address.
+     */
+    public static final int LIMITED_TO_IPV6 = 0x8BB;
+    /** Data call bring up fails in the VSNCP phase due to a VSNCP timeout error. */
+    public static final int VSNCP_TIMEOUT = 0x8BC;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a general error. It's used when there is
+     * no other specific error code available to report the failure.
+     */
+    public static final int VSNCP_GEN_ERROR = 0x8BD;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the requested APN is unauthorized.
+     */
+    public static final int VSNCP_APN_UNATHORIZED = 0x8BE;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN limit has been exceeded.
+     */
+    public static final int VSNCP_PDN_LIMIT_EXCEEDED = 0x8BF;
+    /**
+     * Data call bring up fails in the VSNCP phase due to the network rejected the VSNCP
+     * configuration request due to no PDN gateway address.
+     */
+    public static final int VSNCP_NO_PDN_GATEWAY_ADDRESS = 0x8C0;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN gateway is unreachable.
+     */
+    public static final int VSNCP_PDN_GATEWAY_UNREACHABLE = 0x8C1;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request due to a PDN gateway reject.
+     */
+    public static final int VSNCP_PDN_GATEWAY_REJECT = 0x8C2;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of insufficient parameter.
+     */
+    public static final int VSNCP_INSUFFICIENT_PARAMETERS = 0x8C3;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of resource unavailable.
+     */
+    public static final int VSNCP_RESOURCE_UNAVAILABLE = 0x8C4;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with the reason of administratively prohibited at the HSGW.
+     */
+    public static final int VSNCP_ADMINISTRATIVELY_PROHIBITED = 0x8C5;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of PDN ID in use, or
+     * all existing PDNs are brought down with this end reason because one of the PDN bring up was
+     * rejected by the network with the reason of PDN ID in use.
+     */
+    public static final int VSNCP_PDN_ID_IN_USE = 0x8C6;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request for the reason of subscriber limitation.
+     */
+    public static final int VSNCP_SUBSCRIBER_LIMITATION = 0x8C7;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the PDN exists for this APN.
+     */
+    public static final int VSNCP_PDN_EXISTS_FOR_THIS_APN = 0x8C8;
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request with reconnect to this PDN not allowed, or an active data call is
+     * terminated by the network because reconnection to this PDN is not allowed. Upon receiving
+     * this error code from the network, the modem infinitely throttles the PDN until the next
+     * power cycle.
+     */
+    public static final int VSNCP_RECONNECT_NOT_ALLOWED = 0x8C9;
+    /** Device failure to obtain the prefix from the network. */
+    public static final int IPV6_PREFIX_UNAVAILABLE = 0x8CA;
+    /** System preference change back to SRAT during handoff */
+    public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
 
     // OEM sepecific error codes. To be used by OEMs when they don't
     // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
@@ -226,12 +988,18 @@
             FILTER_SEMANTIC_ERROR,
             FILTER_SYTAX_ERROR,
             PDP_WITHOUT_ACTIVE_TFT,
+            ACTIVATION_REJECTED_BCM_VIOLATION,
             ONLY_IPV4_ALLOWED,
             ONLY_IPV6_ALLOWED,
             ONLY_SINGLE_BEARER_ALLOWED,
             ESM_INFO_NOT_RECEIVED,
             PDN_CONN_DOES_NOT_EXIST,
             MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED,
+            COLLISION_WITH_NETWORK_INITIATED_REQUEST,
+            ONLY_IPV4V6_ALLOWED,
+            ONLY_NON_IP_ALLOWED,
+            UNSUPPORTED_QCI_VALUE,
+            BEARER_HANDLING_NOT_SUPPORTED,
             ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED,
             UNSUPPORTED_APN_IN_CURRENT_PLMN,
             INVALID_TRANSACTION_ID,
@@ -242,7 +1010,7 @@
             UNKNOWN_INFO_ELEMENT,
             CONDITIONAL_IE_ERROR,
             MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE,
-            PROTOCOL_ERRORS,                 /* no retry */
+            PROTOCOL_ERRORS,
             APN_TYPE_CONFLICT,
             INVALID_PCSCF_ADDR,
             INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN,
@@ -254,6 +1022,262 @@
             IFACE_AND_POL_FAMILY_MISMATCH,
             EMM_ACCESS_BARRED_INFINITE_RETRY,
             AUTH_FAILURE_ON_EMERGENCY_CALL,
+            INVALID_DNS_ADDR,
+            INVALID_PCSCF_OR_DNS_ADDRESS,
+            CALL_PREEMPT_BY_EMERGENCY_APN,
+            UE_INITIATED_DETACH_OR_DISCONNECT,
+            MIP_FA_REASON_UNSPECIFIED,
+            MIP_FA_ADMIN_PROHIBITED,
+            MIP_FA_INSUFFICIENT_RESOURCES,
+            MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE,
+            MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE,
+            MIP_FA_REQUESTED_LIFETIME_TOO_LONG,
+            MIP_FA_MALFORMED_REQUEST,
+            MIP_FA_MALFORMED_REPLY,
+            MIP_FA_ENCAPSULATION_UNAVAILABLE,
+            MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE,
+            MIP_FA_REVERSE_TUNNEL_UNAVAILABLE,
+            MIP_FA_REVERSE_TUNNEL_IS_MANDATORY,
+            MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED,
+            MIP_FA_MISSING_NAI,
+            MIP_FA_MISSING_HOME_AGENT,
+            MIP_FA_MISSING_HOME_ADDRESS,
+            MIP_FA_UNKNOWN_CHALLENGE,
+            MIP_FA_MISSING_CHALLENGE,
+            MIP_FA_STALE_CHALLENGE,
+            MIP_HA_REASON_UNSPECIFIED,
+            MIP_HA_ADMIN_PROHIBITED,
+            MIP_HA_INSUFFICIENT_RESOURCES,
+            MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE,
+            MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE,
+            MIP_HA_REGISTRATION_ID_MISMATCH,
+            MIP_HA_MALFORMED_REQUEST,
+            MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS,
+            MIP_HA_REVERSE_TUNNEL_UNAVAILABLE,
+            MIP_HA_REVERSE_TUNNEL_IS_MANDATORY,
+            MIP_HA_ENCAPSULATION_UNAVAILABLE,
+            CLOSE_IN_PROGRESS,
+            NETWORK_INITIATED_TERMINATION,
+            MODEM_APP_PREEMPTED,
+            PDN_IPV4_CALL_DISALLOWED,
+            PDN_IPV4_CALL_THROTTLED,
+            PDN_IPV6_CALL_DISALLOWED,
+            PDN_IPV6_CALL_THROTTLED,
+            MODEM_RESTART,
+            PDP_PPP_NOT_SUPPORTED,
+            UNPREFERRED_RAT,
+            PHYSICAL_LINK_CLOSE_IN_PROGRESS,
+            APN_PENDING_HANDOVER,
+            PROFILE_BEARER_INCOMPATIBLE,
+            SIM_CARD_CHANGED,
+            LOW_POWER_MODE_OR_POWERING_DOWN,
+            APN_DISABLED,
+            MAX_PPP_INACTIVITY_TIMER_EXPIRED,
+            IPV6_ADDRESS_TRANSFER_FAILED,
+            TRAT_SWAP_FAILED,
+            EHRPD_TO_HRPD_FALLBACK,
+            MIP_CONFIG_FAILURE,
+            PDN_INACTIVITY_TIMER_EXPIRED,
+            MAX_IPV4_CONNECTIONS,
+            MAX_IPV6_CONNECTIONS,
+            APN_MISMATCH,
+            IP_VERSION_MISMATCH,
+            DUN_CALL_DISALLOWED,
+            INTERNAL_EPC_NONEPC_TRANSITION,
+            INTERFACE_IN_USE,
+            APN_DISALLOWED_ON_ROAMING,
+            APN_PARAMETERS_CHANGED,
+            NULL_APN_DISALLOWED,
+            THERMAL_MITIGATION,
+            DATA_SETTINGS_DISABLED,
+            DATA_ROAMING_SETTINGS_DISABLED,
+            DDS_SWITCHED,
+            FORBIDDEN_APN_NAME,
+            DDS_SWITCH_IN_PROGRESS,
+            CALL_DISALLOWED_IN_ROAMING,
+            NON_IP_NOT_SUPPORTED,
+            PDN_NON_IP_CALL_THROTTLED,
+            PDN_NON_IP_CALL_DISALLOWED,
+            CDMA_LOCK,
+            CDMA_INTERCEPT,
+            CDMA_REORDER,
+            CDMA_RELEASE_DUE_TO_SO_REJECTION,
+            CDMA_INCOMING_CALL,
+            CDMA_ALERT_STOP,
+            CHANNEL_ACQUISITION_FAILURE,
+            MAX_ACCESS_PROBE,
+            CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
+            NO_RESPONSE_FROM_BASE_STATION,
+            REJECTED_BY_BASE_STATION,
+            CONCURRENT_SERVICES_INCOMPATIBLE,
+            NO_CDMA_SERVICE,
+            RUIM_NOT_PRESENT,
+            CDMA_RETRY_ORDER,
+            ACCESS_BLOCK,
+            ACCESS_BLOCK_ALL,
+            IS707B_MAX_ACCESS_PROBES,
+            THERMAL_EMERGENCY,
+            CONCURRENT_SERVICES_NOT_ALLOWED,
+            INCOMING_CALL_REJECTED,
+            NO_SERVICE_ON_GATEWAY,
+            NO_GPRS_CONTEXT,
+            ILLEGAL_MS,
+            ILLEGAL_ME,
+            GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED,
+            GPRS_SERVICES_NOT_ALLOWED,
+            MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK,
+            IMPLICITLY_DETACHED,
+            PLMN_NOT_ALLOWED,
+            LOCATION_AREA_NOT_ALLOWED,
+            GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN,
+            PDP_DUPLICATE,
+            UE_RAT_CHANGE,
+            CONGESTION,
+            NO_PDP_CONTEXT_ACTIVATED,
+            ACCESS_CLASS_DSAC_REJECTION,
+            PDP_ACTIVATE_MAX_RETRY_FAILED,
+            RADIO_ACCESS_BEARER_FAILURE,
+            ESM_UNKNOWN_EPS_BEARER_CONTEXT,
+            DRB_RELEASED_BY_RRC,
+            CONNECTION_RELEASED,
+            EMM_DETACHED,
+            EMM_ATTACH_FAILED,
+            EMM_ATTACH_STARTED,
+            LTE_NAS_SERVICE_REQUEST_FAILED,
+            DUPLICATE_BEARER_ID,
+            ESM_COLLISION_SCENARIOS,
+            ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK,
+            ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER,
+            ESM_BAD_OTA_MESSAGE,
+            ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL,
+            ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT,
+            DS_EXPLICIT_DEACTIVATION,
+            ESM_LOCAL_CAUSE_NONE,
+            LTE_THROTTLING_NOT_REQUIRED,
+            ACCESS_CONTROL_LIST_CHECK_FAILURE,
+            SERVICE_NOT_ALLOWED_ON_PLMN,
+            EMM_T3417_EXPIRED,
+            EMM_T3417_EXT_EXPIRED,
+            RRC_UPLINK_DATA_TRANSMISSION_FAILURE,
+            RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER,
+            RRC_UPLINK_CONNECTION_RELEASE,
+            RRC_UPLINK_RADIO_LINK_FAILURE,
+            RRC_UPLINK_ERROR_REQUEST_FROM_NAS,
+            RRC_CONNECTION_ACCESS_STRATUM_FAILURE,
+            RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS,
+            RRC_CONNECTION_ACCESS_BARRED,
+            RRC_CONNECTION_CELL_RESELECTION,
+            RRC_CONNECTION_CONFIG_FAILURE,
+            RRC_CONNECTION_TIMER_EXPIRED,
+            RRC_CONNECTION_LINK_FAILURE,
+            RRC_CONNECTION_CELL_NOT_CAMPED,
+            RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE,
+            RRC_CONNECTION_REJECT_BY_NETWORK,
+            RRC_CONNECTION_NORMAL_RELEASE,
+            RRC_CONNECTION_RADIO_LINK_FAILURE,
+            RRC_CONNECTION_REESTABLISHMENT_FAILURE,
+            RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER,
+            RRC_CONNECTION_ABORT_REQUEST,
+            RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR,
+            NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH,
+            NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH,
+            ESM_PROCEDURE_TIME_OUT,
+            INVALID_CONNECTION_ID,
+            MAXIMIUM_NSAPIS_EXCEEDED,
+            INVALID_PRIMARY_NSAPI,
+            CANNOT_ENCODE_OTA_MESSAGE,
+            RADIO_ACCESS_BEARER_SETUP_FAILURE,
+            PDP_ESTABLISH_TIMEOUT_EXPIRED,
+            PDP_MODIFY_TIMEOUT_EXPIRED,
+            PDP_INACTIVE_TIMEOUT_EXPIRED,
+            PDP_LOWERLAYER_ERROR,
+            PDP_MODIFY_COLLISION,
+            MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED,
+            NAS_REQUEST_REJECTED_BY_NETWORK,
+            RRC_CONNECTION_INVALID_REQUEST,
+            RRC_CONNECTION_TRACKING_AREA_ID_CHANGED,
+            RRC_CONNECTION_RF_UNAVAILABLE,
+            RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE,
+            RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE,
+            RRC_CONNECTION_ABORTED_AFTER_HANDOVER,
+            RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE,
+            RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE,
+            IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER,
+            IMEI_NOT_ACCEPTED,
+            EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
+            EPS_SERVICES_NOT_ALLOWED_IN_PLMN,
+            MSC_TEMPORARILY_NOT_REACHABLE,
+            CS_DOMAIN_NOT_AVAILABLE,
+            ESM_FAILURE,
+            MAC_FAILURE,
+            SYNCHRONIZATION_FAILURE,
+            UE_SECURITY_CAPABILITIES_MISMATCH,
+            SECURITY_MODE_REJECTED,
+            UNACCEPTABLE_NON_EPS_AUTHENTICATION,
+            CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED,
+            NO_EPS_BEARER_CONTEXT_ACTIVATED,
+            INVALID_EMM_STATE,
+            NAS_LAYER_FAILURE,
+            MULTIPLE_PDP_CALL_NOT_ALLOWED,
+            EMBMS_NOT_ENABLED,
+            IRAT_HANDOVER_FAILED,
+            EMBMS_REGULAR_DEACTIVATION,
+            TEST_LOOPBACK_REGULAR_DEACTIVATION,
+            LOWER_LAYER_REGISTRATION_FAILURE,
+            DATA_PLAN_EXPIRED,
+            UMTS_HANDOVER_TO_IWLAN,
+            EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY,
+            EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE,
+            EVDO_HDR_CHANGED,
+            EVDO_HDR_EXITED,
+            EVDO_HDR_NO_SESSION,
+            EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL,
+            EVDO_HDR_CONNECTION_SETUP_TIMEOUT,
+            FAILED_TO_ACQUIRE_COLOCATED_HDR,
+            OTASP_COMMIT_IN_PROGRESS,
+            NO_HYBRID_HDR_SERVICE,
+            HDR_NO_LOCK_GRANTED,
+            DBM_OR_SMS_IN_PROGRESS,
+            HDR_FADE,
+            HDR_ACCESS_FAILURE,
+            UNSUPPORTED_1X_PREV,
+            LOCAL_END,
+            NO_SERVICE,
+            FADE,
+            NORMAL_RELEASE,
+            ACCESS_ATTEMPT_ALREADY_IN_PROGRESS,
+            REDIRECTION_OR_HANDOFF_IN_PROGRESS,
+            EMERGENCY_MODE,
+            PHONE_IN_USE,
+            INVALID_MODE,
+            INVALID_SIM_STATE,
+            NO_COLLOCATED_HDR,
+            UE_IS_ENTERING_POWERSAVE_MODE,
+            DUAL_SWITCH,
+            PPP_TIMEOUT,
+            PPP_AUTH_FAILURE,
+            PPP_OPTION_MISMATCH,
+            PPP_PAP_FAILURE,
+            PPP_CHAP_FAILURE,
+            PPP_CLOSE_IN_PROGRESS,
+            LIMITED_TO_IPV4,
+            LIMITED_TO_IPV6,
+            VSNCP_TIMEOUT,
+            VSNCP_GEN_ERROR,
+            VSNCP_APN_UNATHORIZED,
+            VSNCP_PDN_LIMIT_EXCEEDED,
+            VSNCP_NO_PDN_GATEWAY_ADDRESS,
+            VSNCP_PDN_GATEWAY_UNREACHABLE,
+            VSNCP_PDN_GATEWAY_REJECT,
+            VSNCP_INSUFFICIENT_PARAMETERS,
+            VSNCP_RESOURCE_UNAVAILABLE,
+            VSNCP_ADMINISTRATIVELY_PROHIBITED,
+            VSNCP_PDN_ID_IN_USE,
+            VSNCP_SUBSCRIBER_LIMITATION,
+            VSNCP_PDN_EXISTS_FOR_THIS_APN,
+            VSNCP_RECONNECT_NOT_ALLOWED,
+            IPV6_PREFIX_UNAVAILABLE,
+            HANDOFF_PREFERENCE_CHANGED,
             OEM_DCFAILCAUSE_1,
             OEM_DCFAILCAUSE_2,
             OEM_DCFAILCAUSE_3,
@@ -317,6 +1341,7 @@
         sFailCauseMap.put(FILTER_SEMANTIC_ERROR, "FILTER_SEMANTIC_ERROR");
         sFailCauseMap.put(FILTER_SYTAX_ERROR, "FILTER_SYTAX_ERROR");
         sFailCauseMap.put(PDP_WITHOUT_ACTIVE_TFT, "PDP_WITHOUT_ACTIVE_TFT");
+        sFailCauseMap.put(ACTIVATION_REJECTED_BCM_VIOLATION, "ACTIVATION_REJECTED_BCM_VIOLATION");
         sFailCauseMap.put(ONLY_IPV4_ALLOWED, "ONLY_IPV4_ALLOWED");
         sFailCauseMap.put(ONLY_IPV6_ALLOWED, "ONLY_IPV6_ALLOWED");
         sFailCauseMap.put(ONLY_SINGLE_BEARER_ALLOWED, "ONLY_SINGLE_BEARER_ALLOWED");
@@ -324,6 +1349,12 @@
         sFailCauseMap.put(PDN_CONN_DOES_NOT_EXIST, "PDN_CONN_DOES_NOT_EXIST");
         sFailCauseMap.put(MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED,
                 "MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED");
+        sFailCauseMap.put(COLLISION_WITH_NETWORK_INITIATED_REQUEST,
+                "COLLISION_WITH_NETWORK_INITIATED_REQUEST");
+        sFailCauseMap.put(ONLY_IPV4V6_ALLOWED, "ONLY_IPV4V6_ALLOWED");
+        sFailCauseMap.put(ONLY_NON_IP_ALLOWED, "ONLY_NON_IP_ALLOWED");
+        sFailCauseMap.put(UNSUPPORTED_QCI_VALUE, "UNSUPPORTED_QCI_VALUE");
+        sFailCauseMap.put(BEARER_HANDLING_NOT_SUPPORTED, "BEARER_HANDLING_NOT_SUPPORTED");
         sFailCauseMap.put(ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED,
                 "ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED");
         sFailCauseMap.put(UNSUPPORTED_APN_IN_CURRENT_PLMN,
@@ -353,6 +1384,301 @@
                 "EMM_ACCESS_BARRED_INFINITE_RETRY");
         sFailCauseMap.put(AUTH_FAILURE_ON_EMERGENCY_CALL,
                 "AUTH_FAILURE_ON_EMERGENCY_CALL");
+        sFailCauseMap.put(INVALID_DNS_ADDR, "INVALID_DNS_ADDR");
+        sFailCauseMap.put(INVALID_PCSCF_OR_DNS_ADDRESS, "INVALID_PCSCF_OR_DNS_ADDRESS");
+        sFailCauseMap.put(CALL_PREEMPT_BY_EMERGENCY_APN, "CALL_PREEMPT_BY_EMERGENCY_APN");
+        sFailCauseMap.put(UE_INITIATED_DETACH_OR_DISCONNECT, "UE_INITIATED_DETACH_OR_DISCONNECT");
+        sFailCauseMap.put(MIP_FA_REASON_UNSPECIFIED, "MIP_FA_REASON_UNSPECIFIED");
+        sFailCauseMap.put(MIP_FA_ADMIN_PROHIBITED, "MIP_FA_ADMIN_PROHIBITED");
+        sFailCauseMap.put(MIP_FA_INSUFFICIENT_RESOURCES, "MIP_FA_INSUFFICIENT_RESOURCES");
+        sFailCauseMap.put(MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE,
+                "MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE");
+        sFailCauseMap.put(MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE,
+                "MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE");
+        sFailCauseMap.put(MIP_FA_REQUESTED_LIFETIME_TOO_LONG, "MIP_FA_REQUESTED_LIFETIME_TOO_LONG");
+        sFailCauseMap.put(MIP_FA_MALFORMED_REQUEST, "MIP_FA_MALFORMED_REQUEST");
+        sFailCauseMap.put(MIP_FA_MALFORMED_REPLY, "MIP_FA_MALFORMED_REPLY");
+        sFailCauseMap.put(MIP_FA_ENCAPSULATION_UNAVAILABLE, "MIP_FA_ENCAPSULATION_UNAVAILABLE");
+        sFailCauseMap.put(MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE,
+                "MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE");
+        sFailCauseMap.put(MIP_FA_REVERSE_TUNNEL_UNAVAILABLE, "MIP_FA_REVERSE_TUNNEL_UNAVAILABLE");
+        sFailCauseMap.put(MIP_FA_REVERSE_TUNNEL_IS_MANDATORY, "MIP_FA_REVERSE_TUNNEL_IS_MANDATORY");
+        sFailCauseMap.put(MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED,
+                "MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED");
+        sFailCauseMap.put(MIP_FA_MISSING_NAI, "MIP_FA_MISSING_NAI");
+        sFailCauseMap.put(MIP_FA_MISSING_HOME_AGENT, "MIP_FA_MISSING_HOME_AGENT");
+        sFailCauseMap.put(MIP_FA_MISSING_HOME_ADDRESS, "MIP_FA_MISSING_HOME_ADDRESS");
+        sFailCauseMap.put(MIP_FA_UNKNOWN_CHALLENGE, "MIP_FA_UNKNOWN_CHALLENGE");
+        sFailCauseMap.put(MIP_FA_MISSING_CHALLENGE, "MIP_FA_MISSING_CHALLENGE");
+        sFailCauseMap.put(MIP_FA_STALE_CHALLENGE, "MIP_FA_STALE_CHALLENGE");
+        sFailCauseMap.put(MIP_HA_REASON_UNSPECIFIED, "MIP_HA_REASON_UNSPECIFIED");
+        sFailCauseMap.put(MIP_HA_ADMIN_PROHIBITED, "MIP_HA_ADMIN_PROHIBITED");
+        sFailCauseMap.put(MIP_HA_INSUFFICIENT_RESOURCES, "MIP_HA_INSUFFICIENT_RESOURCES");
+        sFailCauseMap.put(MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE,
+                "MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE");
+        sFailCauseMap.put(MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE,
+                "MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE");
+        sFailCauseMap.put(MIP_HA_REGISTRATION_ID_MISMATCH, "MIP_HA_REGISTRATION_ID_MISMATCH");
+        sFailCauseMap.put(MIP_HA_MALFORMED_REQUEST, "MIP_HA_MALFORMED_REQUEST");
+        sFailCauseMap.put(MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS, "MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS");
+        sFailCauseMap.put(MIP_HA_REVERSE_TUNNEL_UNAVAILABLE, "MIP_HA_REVERSE_TUNNEL_UNAVAILABLE");
+        sFailCauseMap.put(MIP_HA_REVERSE_TUNNEL_IS_MANDATORY, "MIP_HA_REVERSE_TUNNEL_IS_MANDATORY");
+        sFailCauseMap.put(MIP_HA_ENCAPSULATION_UNAVAILABLE, "MIP_HA_ENCAPSULATION_UNAVAILABLE");
+        sFailCauseMap.put(CLOSE_IN_PROGRESS, "CLOSE_IN_PROGRESS");
+        sFailCauseMap.put(NETWORK_INITIATED_TERMINATION, "NETWORK_INITIATED_TERMINATION");
+        sFailCauseMap.put(MODEM_APP_PREEMPTED, "MODEM_APP_PREEMPTED");
+        sFailCauseMap.put(PDN_IPV4_CALL_DISALLOWED, "PDN_IPV4_CALL_DISALLOWED");
+        sFailCauseMap.put(PDN_IPV4_CALL_THROTTLED, "PDN_IPV4_CALL_THROTTLED");
+        sFailCauseMap.put(PDN_IPV6_CALL_DISALLOWED, "PDN_IPV6_CALL_DISALLOWED");
+        sFailCauseMap.put(PDN_IPV6_CALL_THROTTLED, "PDN_IPV6_CALL_THROTTLED");
+        sFailCauseMap.put(MODEM_RESTART, "MODEM_RESTART");
+        sFailCauseMap.put(PDP_PPP_NOT_SUPPORTED, "PDP_PPP_NOT_SUPPORTED");
+        sFailCauseMap.put(UNPREFERRED_RAT, "UNPREFERRED_RAT");
+        sFailCauseMap.put(PHYSICAL_LINK_CLOSE_IN_PROGRESS, "PHYSICAL_LINK_CLOSE_IN_PROGRESS");
+        sFailCauseMap.put(APN_PENDING_HANDOVER, "APN_PENDING_HANDOVER");
+        sFailCauseMap.put(PROFILE_BEARER_INCOMPATIBLE, "PROFILE_BEARER_INCOMPATIBLE");
+        sFailCauseMap.put(SIM_CARD_CHANGED, "SIM_CARD_CHANGED");
+        sFailCauseMap.put(LOW_POWER_MODE_OR_POWERING_DOWN, "LOW_POWER_MODE_OR_POWERING_DOWN");
+        sFailCauseMap.put(APN_DISABLED, "APN_DISABLED");
+        sFailCauseMap.put(MAX_PPP_INACTIVITY_TIMER_EXPIRED, "MAX_PPP_INACTIVITY_TIMER_EXPIRED");
+        sFailCauseMap.put(IPV6_ADDRESS_TRANSFER_FAILED, "IPV6_ADDRESS_TRANSFER_FAILED");
+        sFailCauseMap.put(TRAT_SWAP_FAILED, "TRAT_SWAP_FAILED");
+        sFailCauseMap.put(EHRPD_TO_HRPD_FALLBACK, "EHRPD_TO_HRPD_FALLBACK");
+        sFailCauseMap.put(MIP_CONFIG_FAILURE, "MIP_CONFIG_FAILURE");
+        sFailCauseMap.put(PDN_INACTIVITY_TIMER_EXPIRED, "PDN_INACTIVITY_TIMER_EXPIRED");
+        sFailCauseMap.put(MAX_IPV4_CONNECTIONS, "MAX_IPV4_CONNECTIONS");
+        sFailCauseMap.put(MAX_IPV6_CONNECTIONS, "MAX_IPV6_CONNECTIONS");
+        sFailCauseMap.put(APN_MISMATCH, "APN_MISMATCH");
+        sFailCauseMap.put(IP_VERSION_MISMATCH, "IP_VERSION_MISMATCH");
+        sFailCauseMap.put(DUN_CALL_DISALLOWED, "DUN_CALL_DISALLOWED");
+        sFailCauseMap.put(INTERNAL_EPC_NONEPC_TRANSITION, "INTERNAL_EPC_NONEPC_TRANSITION");
+        sFailCauseMap.put(INTERFACE_IN_USE, "INTERFACE_IN_USE");
+        sFailCauseMap.put(APN_DISALLOWED_ON_ROAMING, "APN_DISALLOWED_ON_ROAMING");
+        sFailCauseMap.put(APN_PARAMETERS_CHANGED, "APN_PARAMETERS_CHANGED");
+        sFailCauseMap.put(NULL_APN_DISALLOWED, "NULL_APN_DISALLOWED");
+        sFailCauseMap.put(THERMAL_MITIGATION, "THERMAL_MITIGATION");
+        sFailCauseMap.put(DATA_SETTINGS_DISABLED, "DATA_SETTINGS_DISABLED");
+        sFailCauseMap.put(DATA_ROAMING_SETTINGS_DISABLED, "DATA_ROAMING_SETTINGS_DISABLED");
+        sFailCauseMap.put(DDS_SWITCHED, "DDS_SWITCHED");
+        sFailCauseMap.put(FORBIDDEN_APN_NAME, "FORBIDDEN_APN_NAME");
+        sFailCauseMap.put(DDS_SWITCH_IN_PROGRESS, "DDS_SWITCH_IN_PROGRESS");
+        sFailCauseMap.put(CALL_DISALLOWED_IN_ROAMING, "CALL_DISALLOWED_IN_ROAMING");
+        sFailCauseMap.put(NON_IP_NOT_SUPPORTED, "NON_IP_NOT_SUPPORTED");
+        sFailCauseMap.put(PDN_NON_IP_CALL_THROTTLED, "PDN_NON_IP_CALL_THROTTLED");
+        sFailCauseMap.put(PDN_NON_IP_CALL_DISALLOWED, "PDN_NON_IP_CALL_DISALLOWED");
+        sFailCauseMap.put(CDMA_LOCK, "CDMA_LOCK");
+        sFailCauseMap.put(CDMA_INTERCEPT, "CDMA_INTERCEPT");
+        sFailCauseMap.put(CDMA_REORDER, "CDMA_REORDER");
+        sFailCauseMap.put(CDMA_RELEASE_DUE_TO_SO_REJECTION, "CDMA_RELEASE_DUE_TO_SO_REJECTION");
+        sFailCauseMap.put(CDMA_INCOMING_CALL, "CDMA_INCOMING_CALL");
+        sFailCauseMap.put(CDMA_ALERT_STOP, "CDMA_ALERT_STOP");
+        sFailCauseMap.put(CHANNEL_ACQUISITION_FAILURE, "CHANNEL_ACQUISITION_FAILURE");
+        sFailCauseMap.put(MAX_ACCESS_PROBE, "MAX_ACCESS_PROBE");
+        sFailCauseMap.put(CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION,
+                "CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION");
+        sFailCauseMap.put(NO_RESPONSE_FROM_BASE_STATION, "NO_RESPONSE_FROM_BASE_STATION");
+        sFailCauseMap.put(REJECTED_BY_BASE_STATION, "REJECTED_BY_BASE_STATION");
+        sFailCauseMap.put(CONCURRENT_SERVICES_INCOMPATIBLE, "CONCURRENT_SERVICES_INCOMPATIBLE");
+        sFailCauseMap.put(NO_CDMA_SERVICE, "NO_CDMA_SERVICE");
+        sFailCauseMap.put(RUIM_NOT_PRESENT, "RUIM_NOT_PRESENT");
+        sFailCauseMap.put(CDMA_RETRY_ORDER, "CDMA_RETRY_ORDER");
+        sFailCauseMap.put(ACCESS_BLOCK, "ACCESS_BLOCK");
+        sFailCauseMap.put(ACCESS_BLOCK_ALL, "ACCESS_BLOCK_ALL");
+        sFailCauseMap.put(IS707B_MAX_ACCESS_PROBES, "IS707B_MAX_ACCESS_PROBES");
+        sFailCauseMap.put(THERMAL_EMERGENCY, "THERMAL_EMERGENCY");
+        sFailCauseMap.put(CONCURRENT_SERVICES_NOT_ALLOWED, "CONCURRENT_SERVICES_NOT_ALLOWED");
+        sFailCauseMap.put(INCOMING_CALL_REJECTED, "INCOMING_CALL_REJECTED");
+        sFailCauseMap.put(NO_SERVICE_ON_GATEWAY, "NO_SERVICE_ON_GATEWAY");
+        sFailCauseMap.put(NO_GPRS_CONTEXT, "NO_GPRS_CONTEXT");
+        sFailCauseMap.put(ILLEGAL_MS, "ILLEGAL_MS");
+        sFailCauseMap.put(ILLEGAL_ME, "ILLEGAL_ME");
+        sFailCauseMap.put(GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED,
+                "GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED");
+        sFailCauseMap.put(GPRS_SERVICES_NOT_ALLOWED, "GPRS_SERVICES_NOT_ALLOWED");
+        sFailCauseMap.put(MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK,
+                "MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK");
+        sFailCauseMap.put(IMPLICITLY_DETACHED, "IMPLICITLY_DETACHED");
+        sFailCauseMap.put(PLMN_NOT_ALLOWED, "PLMN_NOT_ALLOWED");
+        sFailCauseMap.put(LOCATION_AREA_NOT_ALLOWED, "LOCATION_AREA_NOT_ALLOWED");
+        sFailCauseMap.put(GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN,
+                "GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN");
+        sFailCauseMap.put(PDP_DUPLICATE, "PDP_DUPLICATE");
+        sFailCauseMap.put(UE_RAT_CHANGE, "UE_RAT_CHANGE");
+        sFailCauseMap.put(CONGESTION, "CONGESTION");
+        sFailCauseMap.put(NO_PDP_CONTEXT_ACTIVATED, "NO_PDP_CONTEXT_ACTIVATED");
+        sFailCauseMap.put(ACCESS_CLASS_DSAC_REJECTION, "ACCESS_CLASS_DSAC_REJECTION");
+        sFailCauseMap.put(PDP_ACTIVATE_MAX_RETRY_FAILED, "PDP_ACTIVATE_MAX_RETRY_FAILED");
+        sFailCauseMap.put(RADIO_ACCESS_BEARER_FAILURE, "RADIO_ACCESS_BEARER_FAILURE");
+        sFailCauseMap.put(ESM_UNKNOWN_EPS_BEARER_CONTEXT, "ESM_UNKNOWN_EPS_BEARER_CONTEXT");
+        sFailCauseMap.put(DRB_RELEASED_BY_RRC, "DRB_RELEASED_BY_RRC");
+        sFailCauseMap.put(CONNECTION_RELEASED, "CONNECTION_RELEASED");
+        sFailCauseMap.put(EMM_DETACHED, "EMM_DETACHED");
+        sFailCauseMap.put(EMM_ATTACH_FAILED, "EMM_ATTACH_FAILED");
+        sFailCauseMap.put(EMM_ATTACH_STARTED, "EMM_ATTACH_STARTED");
+        sFailCauseMap.put(LTE_NAS_SERVICE_REQUEST_FAILED, "LTE_NAS_SERVICE_REQUEST_FAILED");
+        sFailCauseMap.put(DUPLICATE_BEARER_ID, "DUPLICATE_BEARER_ID");
+        sFailCauseMap.put(ESM_COLLISION_SCENARIOS, "ESM_COLLISION_SCENARIOS");
+        sFailCauseMap.put(ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK,
+                "ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK");
+        sFailCauseMap.put(ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER,
+                "ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER");
+        sFailCauseMap.put(ESM_BAD_OTA_MESSAGE, "ESM_BAD_OTA_MESSAGE");
+        sFailCauseMap.put(ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL,
+                "ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL");
+        sFailCauseMap.put(ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT,
+                "ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT");
+        sFailCauseMap.put(DS_EXPLICIT_DEACTIVATION, "DS_EXPLICIT_DEACTIVATION");
+        sFailCauseMap.put(ESM_LOCAL_CAUSE_NONE, "ESM_LOCAL_CAUSE_NONE");
+        sFailCauseMap.put(LTE_THROTTLING_NOT_REQUIRED, "LTE_THROTTLING_NOT_REQUIRED");
+        sFailCauseMap.put(ACCESS_CONTROL_LIST_CHECK_FAILURE,
+                "ACCESS_CONTROL_LIST_CHECK_FAILURE");
+        sFailCauseMap.put(SERVICE_NOT_ALLOWED_ON_PLMN, "SERVICE_NOT_ALLOWED_ON_PLMN");
+        sFailCauseMap.put(EMM_T3417_EXPIRED, "EMM_T3417_EXPIRED");
+        sFailCauseMap.put(EMM_T3417_EXT_EXPIRED, "EMM_T3417_EXT_EXPIRED");
+        sFailCauseMap.put(RRC_UPLINK_DATA_TRANSMISSION_FAILURE,
+                "RRC_UPLINK_DATA_TRANSMISSION_FAILURE");
+        sFailCauseMap.put(RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER,
+                "RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER");
+        sFailCauseMap.put(RRC_UPLINK_CONNECTION_RELEASE, "RRC_UPLINK_CONNECTION_RELEASE");
+        sFailCauseMap.put(RRC_UPLINK_RADIO_LINK_FAILURE, "RRC_UPLINK_RADIO_LINK_FAILURE");
+        sFailCauseMap.put(RRC_UPLINK_ERROR_REQUEST_FROM_NAS, "RRC_UPLINK_ERROR_REQUEST_FROM_NAS");
+        sFailCauseMap.put(RRC_CONNECTION_ACCESS_STRATUM_FAILURE,
+                "RRC_CONNECTION_ACCESS_STRATUM_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS,
+                "RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS");
+        sFailCauseMap.put(RRC_CONNECTION_ACCESS_BARRED, "RRC_CONNECTION_ACCESS_BARRED");
+        sFailCauseMap.put(RRC_CONNECTION_CELL_RESELECTION, "RRC_CONNECTION_CELL_RESELECTION");
+        sFailCauseMap.put(RRC_CONNECTION_CONFIG_FAILURE, "RRC_CONNECTION_CONFIG_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_TIMER_EXPIRED, "RRC_CONNECTION_TIMER_EXPIRED");
+        sFailCauseMap.put(RRC_CONNECTION_LINK_FAILURE, "RRC_CONNECTION_LINK_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_CELL_NOT_CAMPED, "RRC_CONNECTION_CELL_NOT_CAMPED");
+        sFailCauseMap.put(RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE,
+                "RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_REJECT_BY_NETWORK, "RRC_CONNECTION_REJECT_BY_NETWORK");
+        sFailCauseMap.put(RRC_CONNECTION_NORMAL_RELEASE, "RRC_CONNECTION_NORMAL_RELEASE");
+        sFailCauseMap.put(RRC_CONNECTION_RADIO_LINK_FAILURE, "RRC_CONNECTION_RADIO_LINK_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_REESTABLISHMENT_FAILURE,
+                "RRC_CONNECTION_REESTABLISHMENT_FAILURE");
+        sFailCauseMap.put(RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER,
+                "RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER");
+        sFailCauseMap.put(RRC_CONNECTION_ABORT_REQUEST, "RRC_CONNECTION_ABORT_REQUEST");
+        sFailCauseMap.put(RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR,
+                "RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR");
+        sFailCauseMap.put(NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH,
+                "NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH");
+        sFailCauseMap.put(NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH,
+                "NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH");
+        sFailCauseMap.put(ESM_PROCEDURE_TIME_OUT, "ESM_PROCEDURE_TIME_OUT");
+        sFailCauseMap.put(INVALID_CONNECTION_ID, "INVALID_CONNECTION_ID");
+        sFailCauseMap.put(MAXIMIUM_NSAPIS_EXCEEDED, "MAXIMIUM_NSAPIS_EXCEEDED");
+        sFailCauseMap.put(INVALID_PRIMARY_NSAPI, "INVALID_PRIMARY_NSAPI");
+        sFailCauseMap.put(CANNOT_ENCODE_OTA_MESSAGE, "CANNOT_ENCODE_OTA_MESSAGE");
+        sFailCauseMap.put(RADIO_ACCESS_BEARER_SETUP_FAILURE, "RADIO_ACCESS_BEARER_SETUP_FAILURE");
+        sFailCauseMap.put(PDP_ESTABLISH_TIMEOUT_EXPIRED, "PDP_ESTABLISH_TIMEOUT_EXPIRED");
+        sFailCauseMap.put(PDP_MODIFY_TIMEOUT_EXPIRED, "PDP_MODIFY_TIMEOUT_EXPIRED");
+        sFailCauseMap.put(PDP_INACTIVE_TIMEOUT_EXPIRED, "PDP_INACTIVE_TIMEOUT_EXPIRED");
+        sFailCauseMap.put(PDP_LOWERLAYER_ERROR, "PDP_LOWERLAYER_ERROR");
+        sFailCauseMap.put(PDP_MODIFY_COLLISION, "PDP_MODIFY_COLLISION");
+        sFailCauseMap.put(MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED,
+                "MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED");
+        sFailCauseMap.put(NAS_REQUEST_REJECTED_BY_NETWORK, "NAS_REQUEST_REJECTED_BY_NETWORK");
+        sFailCauseMap.put(RRC_CONNECTION_INVALID_REQUEST, "RRC_CONNECTION_INVALID_REQUEST");
+        sFailCauseMap.put(RRC_CONNECTION_TRACKING_AREA_ID_CHANGED,
+                "RRC_CONNECTION_TRACKING_AREA_ID_CHANGED");
+        sFailCauseMap.put(RRC_CONNECTION_RF_UNAVAILABLE, "RRC_CONNECTION_RF_UNAVAILABLE");
+        sFailCauseMap.put(RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE,
+                "RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE");
+        sFailCauseMap.put(RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE,
+                "RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE");
+        sFailCauseMap.put(RRC_CONNECTION_ABORTED_AFTER_HANDOVER,
+                "RRC_CONNECTION_ABORTED_AFTER_HANDOVER");
+        sFailCauseMap.put(RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE,
+                "RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE");
+        sFailCauseMap.put(RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE,
+                "RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE");
+        sFailCauseMap.put(IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER,
+                "IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER");
+        sFailCauseMap.put(IMEI_NOT_ACCEPTED, "IMEI_NOT_ACCEPTED");
+        sFailCauseMap.put(EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED,
+                "EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED");
+        sFailCauseMap.put(EPS_SERVICES_NOT_ALLOWED_IN_PLMN, "EPS_SERVICES_NOT_ALLOWED_IN_PLMN");
+        sFailCauseMap.put(MSC_TEMPORARILY_NOT_REACHABLE, "MSC_TEMPORARILY_NOT_REACHABLE");
+        sFailCauseMap.put(CS_DOMAIN_NOT_AVAILABLE, "CS_DOMAIN_NOT_AVAILABLE");
+        sFailCauseMap.put(ESM_FAILURE, "ESM_FAILURE");
+        sFailCauseMap.put(MAC_FAILURE, "MAC_FAILURE");
+        sFailCauseMap.put(SYNCHRONIZATION_FAILURE, "SYNCHRONIZATION_FAILURE");
+        sFailCauseMap.put(UE_SECURITY_CAPABILITIES_MISMATCH, "UE_SECURITY_CAPABILITIES_MISMATCH");
+        sFailCauseMap.put(SECURITY_MODE_REJECTED, "SECURITY_MODE_REJECTED");
+        sFailCauseMap.put(UNACCEPTABLE_NON_EPS_AUTHENTICATION,
+                "UNACCEPTABLE_NON_EPS_AUTHENTICATION");
+        sFailCauseMap.put(CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED,
+                "CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED");
+        sFailCauseMap.put(NO_EPS_BEARER_CONTEXT_ACTIVATED, "NO_EPS_BEARER_CONTEXT_ACTIVATED");
+        sFailCauseMap.put(INVALID_EMM_STATE, "INVALID_EMM_STATE");
+        sFailCauseMap.put(NAS_LAYER_FAILURE, "NAS_LAYER_FAILURE");
+        sFailCauseMap.put(MULTIPLE_PDP_CALL_NOT_ALLOWED, "MULTIPLE_PDP_CALL_NOT_ALLOWED");
+        sFailCauseMap.put(EMBMS_NOT_ENABLED, "EMBMS_NOT_ENABLED");
+        sFailCauseMap.put(IRAT_HANDOVER_FAILED, "IRAT_HANDOVER_FAILED");
+        sFailCauseMap.put(EMBMS_REGULAR_DEACTIVATION, "EMBMS_REGULAR_DEACTIVATION");
+        sFailCauseMap.put(TEST_LOOPBACK_REGULAR_DEACTIVATION, "TEST_LOOPBACK_REGULAR_DEACTIVATION");
+        sFailCauseMap.put(LOWER_LAYER_REGISTRATION_FAILURE, "LOWER_LAYER_REGISTRATION_FAILURE");
+        sFailCauseMap.put(DATA_PLAN_EXPIRED, "DATA_PLAN_EXPIRED");
+        sFailCauseMap.put(UMTS_HANDOVER_TO_IWLAN, "UMTS_HANDOVER_TO_IWLAN");
+        sFailCauseMap.put(EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY,
+                "EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY");
+        sFailCauseMap.put(EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE,
+                "EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE");
+        sFailCauseMap.put(EVDO_HDR_CHANGED, "EVDO_HDR_CHANGED");
+        sFailCauseMap.put(EVDO_HDR_EXITED, "EVDO_HDR_EXITED");
+        sFailCauseMap.put(EVDO_HDR_NO_SESSION, "EVDO_HDR_NO_SESSION");
+        sFailCauseMap.put(EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL,
+                "EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL");
+        sFailCauseMap.put(EVDO_HDR_CONNECTION_SETUP_TIMEOUT, "EVDO_HDR_CONNECTION_SETUP_TIMEOUT");
+        sFailCauseMap.put(FAILED_TO_ACQUIRE_COLOCATED_HDR, "FAILED_TO_ACQUIRE_COLOCATED_HDR");
+        sFailCauseMap.put(OTASP_COMMIT_IN_PROGRESS, "OTASP_COMMIT_IN_PROGRESS");
+        sFailCauseMap.put(NO_HYBRID_HDR_SERVICE, "NO_HYBRID_HDR_SERVICE");
+        sFailCauseMap.put(HDR_NO_LOCK_GRANTED, "HDR_NO_LOCK_GRANTED");
+        sFailCauseMap.put(DBM_OR_SMS_IN_PROGRESS, "DBM_OR_SMS_IN_PROGRESS");
+        sFailCauseMap.put(HDR_FADE, "HDR_FADE");
+        sFailCauseMap.put(HDR_ACCESS_FAILURE, "HDR_ACCESS_FAILURE");
+        sFailCauseMap.put(UNSUPPORTED_1X_PREV, "UNSUPPORTED_1X_PREV");
+        sFailCauseMap.put(LOCAL_END, "LOCAL_END");
+        sFailCauseMap.put(NO_SERVICE, "NO_SERVICE");
+        sFailCauseMap.put(FADE, "FADE");
+        sFailCauseMap.put(NORMAL_RELEASE, "NORMAL_RELEASE");
+        sFailCauseMap.put(ACCESS_ATTEMPT_ALREADY_IN_PROGRESS, "ACCESS_ATTEMPT_ALREADY_IN_PROGRESS");
+        sFailCauseMap.put(REDIRECTION_OR_HANDOFF_IN_PROGRESS, "REDIRECTION_OR_HANDOFF_IN_PROGRESS");
+        sFailCauseMap.put(EMERGENCY_MODE, "EMERGENCY_MODE");
+        sFailCauseMap.put(PHONE_IN_USE, "PHONE_IN_USE");
+        sFailCauseMap.put(INVALID_MODE, "INVALID_MODE");
+        sFailCauseMap.put(INVALID_SIM_STATE, "INVALID_SIM_STATE");
+        sFailCauseMap.put(NO_COLLOCATED_HDR, "NO_COLLOCATED_HDR");
+        sFailCauseMap.put(UE_IS_ENTERING_POWERSAVE_MODE, "UE_IS_ENTERING_POWERSAVE_MODE");
+        sFailCauseMap.put(DUAL_SWITCH, "DUAL_SWITCH");
+        sFailCauseMap.put(PPP_TIMEOUT, "PPP_TIMEOUT");
+        sFailCauseMap.put(PPP_AUTH_FAILURE, "PPP_AUTH_FAILURE");
+        sFailCauseMap.put(PPP_OPTION_MISMATCH, "PPP_OPTION_MISMATCH");
+        sFailCauseMap.put(PPP_PAP_FAILURE, "PPP_PAP_FAILURE");
+        sFailCauseMap.put(PPP_CHAP_FAILURE, "PPP_CHAP_FAILURE");
+        sFailCauseMap.put(PPP_CLOSE_IN_PROGRESS, "PPP_CLOSE_IN_PROGRESS");
+        sFailCauseMap.put(LIMITED_TO_IPV4, "LIMITED_TO_IPV4");
+        sFailCauseMap.put(LIMITED_TO_IPV6, "LIMITED_TO_IPV6");
+        sFailCauseMap.put(VSNCP_TIMEOUT, "VSNCP_TIMEOUT");
+        sFailCauseMap.put(VSNCP_GEN_ERROR, "VSNCP_GEN_ERROR");
+        sFailCauseMap.put(VSNCP_APN_UNATHORIZED, "VSNCP_APN_UNATHORIZED");
+        sFailCauseMap.put(VSNCP_PDN_LIMIT_EXCEEDED, "VSNCP_PDN_LIMIT_EXCEEDED");
+        sFailCauseMap.put(VSNCP_NO_PDN_GATEWAY_ADDRESS, "VSNCP_NO_PDN_GATEWAY_ADDRESS");
+        sFailCauseMap.put(VSNCP_PDN_GATEWAY_UNREACHABLE, "VSNCP_PDN_GATEWAY_UNREACHABLE");
+        sFailCauseMap.put(VSNCP_PDN_GATEWAY_REJECT, "VSNCP_PDN_GATEWAY_REJECT");
+        sFailCauseMap.put(VSNCP_INSUFFICIENT_PARAMETERS, "VSNCP_INSUFFICIENT_PARAMETERS");
+        sFailCauseMap.put(VSNCP_RESOURCE_UNAVAILABLE, "VSNCP_RESOURCE_UNAVAILABLE");
+        sFailCauseMap.put(VSNCP_ADMINISTRATIVELY_PROHIBITED, "VSNCP_ADMINISTRATIVELY_PROHIBITED");
+        sFailCauseMap.put(VSNCP_PDN_ID_IN_USE, "VSNCP_PDN_ID_IN_USE");
+        sFailCauseMap.put(VSNCP_SUBSCRIBER_LIMITATION, "VSNCP_SUBSCRIBER_LIMITATION");
+        sFailCauseMap.put(VSNCP_PDN_EXISTS_FOR_THIS_APN, "VSNCP_PDN_EXISTS_FOR_THIS_APN");
+        sFailCauseMap.put(VSNCP_RECONNECT_NOT_ALLOWED, "VSNCP_RECONNECT_NOT_ALLOWED");
+        sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE");
+        sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED");
         sFailCauseMap.put(OEM_DCFAILCAUSE_1, "OEM_DCFAILCAUSE_1");
         sFailCauseMap.put(OEM_DCFAILCAUSE_2, "OEM_DCFAILCAUSE_2");
         sFailCauseMap.put(OEM_DCFAILCAUSE_3, "OEM_DCFAILCAUSE_3");
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 8d148c3..0e69530 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -140,15 +140,19 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface AuthType {}
 
-    // Possible values for protocol.
-    /** Protocol type for IP. */
+    // Possible values for protocol which is defined in TS 27.007 section 10.1.1.
+    /** Internet protocol. */
     public static final int PROTOCOL_IP = 0;
-    /** Protocol type for IPV6. */
+    /** Internet protocol, version 6. */
     public static final int PROTOCOL_IPV6 = 1;
-    /** Protocol type for IPV4V6. */
+    /** Virtual PDP type introduced to handle dual IP stack UE capability. */
     public static final int PROTOCOL_IPV4V6 = 2;
-    /** Protocol type for PPP. */
+    /** Point to point protocol. */
     public static final int PROTOCOL_PPP = 3;
+    /** Transfer of Non-IP data to external packet data network. */
+    public static final int PROTOCOL_NON_IP = 4;
+    /** Transfer of Unstructured data to the Data Network via N6. */
+    public static final int PROTOCOL_UNSTRUCTURED = 5;
 
     /** @hide */
     @IntDef(prefix = { "PROTOCOL_" }, value = {
@@ -156,6 +160,8 @@
         PROTOCOL_IPV6,
         PROTOCOL_IPV4V6,
         PROTOCOL_PPP,
+        PROTOCOL_NON_IP,
+        PROTOCOL_UNSTRUCTURED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtocolType {}
@@ -217,11 +223,15 @@
         PROTOCOL_STRING_MAP.put("IPV6", PROTOCOL_IPV6);
         PROTOCOL_STRING_MAP.put("IPV4V6", PROTOCOL_IPV4V6);
         PROTOCOL_STRING_MAP.put("PPP", PROTOCOL_PPP);
+        PROTOCOL_STRING_MAP.put("NON-IP", PROTOCOL_NON_IP);
+        PROTOCOL_STRING_MAP.put("UNSTRUCTURED", PROTOCOL_UNSTRUCTURED);
         PROTOCOL_INT_MAP = new ArrayMap<Integer, String>();
         PROTOCOL_INT_MAP.put(PROTOCOL_IP, "IP");
         PROTOCOL_INT_MAP.put(PROTOCOL_IPV6, "IPV6");
         PROTOCOL_INT_MAP.put(PROTOCOL_IPV4V6, "IPV4V6");
         PROTOCOL_INT_MAP.put(PROTOCOL_PPP, "PPP");
+        PROTOCOL_INT_MAP.put(PROTOCOL_NON_IP, "NON-IP");
+        PROTOCOL_INT_MAP.put(PROTOCOL_UNSTRUCTURED, "UNSTRUCTURED");
 
         MVNO_TYPE_STRING_MAP = new ArrayMap<String, Integer>();
         MVNO_TYPE_STRING_MAP.put("spn", MVNO_TYPE_SPN);
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 25f5133..294c79b 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -52,8 +52,7 @@
      * @param status Data call fail cause. 0 indicates no error.
      * @param suggestedRetryTime The suggested data retry time in milliseconds.
      * @param cid The unique id of the data connection.
-     * @param active Data connection active status. 0 = inactive, 1 = active/physical link down,
-     *               2 = active/physical link up.
+     * @param active Data connection active status. 0 = inactive, 1 = dormant, 2 = active.
      * @param type The connection protocol, should be one of the PDP_type values in TS 27.007
      *             section 10.1.1. For example, "IP", "IPV6", "IPV4V6", or "PPP".
      * @param ifname The network interface name.
@@ -124,7 +123,7 @@
     public int getCallId() { return mCid; }
 
     /**
-     * @return 0 = inactive, 1 = active/physical link down, 2 = active/physical link up.
+     * @return 0 = inactive, 1 = dormant, 2 = active.
      */
     public int getActive() { return mActive; }
 
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index a181bc38..1110790 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -32,7 +32,6 @@
 
   public class MockContext extends android.content.Context {
     ctor public MockContext();
-    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -81,7 +80,6 @@
     method public java.io.File getNoBackupFilesDir();
     method public java.io.File getObbDir();
     method public java.io.File[] getObbDirs();
-    method public String getOpPackageName();
     method public String getPackageCodePath();
     method public android.content.pm.PackageManager getPackageManager();
     method public String getPackageName();
@@ -137,7 +135,6 @@
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
-    method public void updateServiceGroup(android.content.ServiceConnection, int, int);
   }
 
   @Deprecated public class MockCursor implements android.database.Cursor {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8c00ceb..e200962 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3717,10 +3717,8 @@
      * @param SSID, in the format of WifiConfiguration's SSID.
      * @hide
      */
-    @SystemApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.NETWORK_SETTINGS,
-            android.Manifest.permission.NETWORK_SETUP_WIZARD,
             android.Manifest.permission.NETWORK_STACK
     })
     public void disableEphemeralNetwork(String SSID) {
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index aa1669e..52ee742 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -28,6 +28,7 @@
 import android.net.NetworkSpecifier;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.Objects;
 
@@ -50,12 +51,24 @@
      */
     private final int mOriginalRequestorUid;
 
+    /**
+     * The package name of the app that requested a specific wifi network using
+     * {@link WifiNetworkSpecifier}.
+     *
+     * Will only be filled when the device connects to a wifi network as a result of a
+     * {@link NetworkRequest} with {@link WifiNetworkSpecifier}. Will be set to null if the device
+     * auto-connected to a wifi network.
+     */
+    private final String mOriginalRequestorPackageName;
+
     public WifiNetworkAgentSpecifier(@NonNull WifiConfiguration wifiConfiguration,
-                                     int originalRequestorUid) {
+                                     int originalRequestorUid,
+                                     @Nullable String originalRequestorPackageName) {
         checkNotNull(wifiConfiguration);
 
         mWifiConfiguration = wifiConfiguration;
         mOriginalRequestorUid = originalRequestorUid;
+        mOriginalRequestorPackageName = originalRequestorPackageName;
     }
 
     /**
@@ -67,7 +80,9 @@
                 public WifiNetworkAgentSpecifier createFromParcel(@NonNull Parcel in) {
                     WifiConfiguration wifiConfiguration = in.readParcelable(null);
                     int originalRequestorUid = in.readInt();
-                    return new WifiNetworkAgentSpecifier(wifiConfiguration, originalRequestorUid);
+                    String originalRequestorPackageName = in.readString();
+                    return new WifiNetworkAgentSpecifier(
+                            wifiConfiguration, originalRequestorUid, originalRequestorPackageName);
                 }
 
                 @Override
@@ -85,6 +100,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelable(mWifiConfiguration, flags);
         dest.writeInt(mOriginalRequestorUid);
+        dest.writeString(mOriginalRequestorPackageName);
     }
 
     @Override
@@ -137,6 +153,9 @@
         if (ns.requestorUid != this.mOriginalRequestorUid) {
             return false;
         }
+        if (!TextUtils.equals(ns.requestorPackageName, this.mOriginalRequestorPackageName)) {
+            return false;
+        }
         return true;
     }
 
@@ -146,7 +165,8 @@
                 mWifiConfiguration.SSID,
                 mWifiConfiguration.BSSID,
                 mWifiConfiguration.allowedKeyManagement,
-                mOriginalRequestorUid);
+                mOriginalRequestorUid,
+                mOriginalRequestorPackageName);
     }
 
     @Override
@@ -162,7 +182,9 @@
                 && Objects.equals(this.mWifiConfiguration.BSSID, lhs.mWifiConfiguration.BSSID)
                 && Objects.equals(this.mWifiConfiguration.allowedKeyManagement,
                     lhs.mWifiConfiguration.allowedKeyManagement)
-                && mOriginalRequestorUid == lhs.mOriginalRequestorUid;
+                && mOriginalRequestorUid == lhs.mOriginalRequestorUid
+                && TextUtils.equals(mOriginalRequestorPackageName,
+                lhs.mOriginalRequestorPackageName);
     }
 
     @Override
@@ -172,6 +194,7 @@
                 .append(", SSID=").append(mWifiConfiguration.SSID)
                 .append(", BSSID=").append(mWifiConfiguration.BSSID)
                 .append(", mOriginalRequestorUid=").append(mOriginalRequestorUid)
+                .append(", mOriginalRequestorPackageName=").append(mOriginalRequestorPackageName)
                 .append("]");
         return sb.toString();
     }
diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
index ecee5ff0..42d4393 100644
--- a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
+++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityThread;
 import android.net.MacAddress;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
@@ -586,7 +587,8 @@
                 mSsidPatternMatcher,
                 mBssidPatternMatcher,
                 buildWifiConfiguration(),
-                Process.myUid());
+                Process.myUid(),
+                ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
     }
 
     /**
@@ -648,7 +650,8 @@
                 buildWifiConfiguration(),
                 mIsAppInteractionRequired,
                 mIsUserInteractionRequired,
-                Process.myUid());
+                Process.myUid(),
+                ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
 
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index 6e4eeef..a5f4675 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -25,6 +25,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.text.TextUtils;
 import android.util.Pair;
 
 import java.util.Objects;
@@ -63,18 +64,25 @@
      */
     public final int requestorUid;
 
+    /**
+     * The package name of the app initializing this network specifier.
+     */
+    public final String requestorPackageName;
+
     public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher,
                  @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher,
                  @NonNull WifiConfiguration wifiConfiguration,
-                 int requestorUid) {
+                 int requestorUid, @NonNull String requestorPackageName) {
         checkNotNull(ssidPatternMatcher);
         checkNotNull(bssidPatternMatcher);
         checkNotNull(wifiConfiguration);
+        checkNotNull(requestorPackageName);
 
         this.ssidPatternMatcher = ssidPatternMatcher;
         this.bssidPatternMatcher = bssidPatternMatcher;
         this.wifiConfiguration = wifiConfiguration;
         this.requestorUid = requestorUid;
+        this.requestorPackageName = requestorPackageName;
     }
 
     public static final Creator<WifiNetworkSpecifier> CREATOR =
@@ -88,8 +96,9 @@
                             Pair.create(baseAddress, mask);
                     WifiConfiguration wifiConfiguration = in.readParcelable(null);
                     int requestorUid = in.readInt();
+                    String requestorPackageName = in.readString();
                     return new WifiNetworkSpecifier(ssidPatternMatcher, bssidPatternMatcher,
-                            wifiConfiguration, requestorUid);
+                            wifiConfiguration, requestorUid, requestorPackageName);
                 }
 
                 @Override
@@ -110,6 +119,7 @@
         dest.writeParcelable(bssidPatternMatcher.second, flags);
         dest.writeParcelable(wifiConfiguration, flags);
         dest.writeInt(requestorUid);
+        dest.writeString(requestorPackageName);
     }
 
     @Override
@@ -136,7 +146,7 @@
                 ssidPatternMatcher.getType(),
                 bssidPatternMatcher,
                 wifiConfiguration.allowedKeyManagement,
-                requestorUid);
+                requestorUid, requestorPackageName);
     }
 
     @Override
@@ -156,7 +166,8 @@
                     lhs.bssidPatternMatcher)
                 && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
                     lhs.wifiConfiguration.allowedKeyManagement)
-                && requestorUid == lhs.requestorUid;
+                && requestorUid == lhs.requestorUid
+                && TextUtils.equals(requestorPackageName, lhs.requestorPackageName);
     }
 
     @Override
@@ -168,6 +179,7 @@
                 .append(", SSID=").append(wifiConfiguration.SSID)
                 .append(", BSSID=").append(wifiConfiguration.BSSID)
                 .append(", requestorUid=").append(requestorUid)
+                .append(", requestorPackageName=").append(requestorPackageName)
                 .append("]")
                 .toString();
     }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 3c90eb7..6b05dfc 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -18,8 +18,10 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 
 import java.util.List;
 import java.util.Objects;
@@ -58,17 +60,25 @@
      */
     public final int suggestorUid;
 
+    /**
+     * The package name of the process initializing this network suggestion.
+     * @hide
+     */
+    public final String suggestorPackageName;
+
     /** @hide */
-    public WifiNetworkSuggestion(WifiConfiguration wifiConfiguration,
+    public WifiNetworkSuggestion(@NonNull WifiConfiguration wifiConfiguration,
                                  boolean isAppInteractionRequired,
                                  boolean isUserInteractionRequired,
-                                 int suggestorUid) {
+                                 int suggestorUid, @NonNull String suggestorPackageName) {
         checkNotNull(wifiConfiguration);
+        checkNotNull(suggestorPackageName);
 
         this.wifiConfiguration = wifiConfiguration;
         this.isAppInteractionRequired = isAppInteractionRequired;
         this.isUserInteractionRequired = isUserInteractionRequired;
         this.suggestorUid = suggestorUid;
+        this.suggestorPackageName = suggestorPackageName;
     }
 
     public static final Creator<WifiNetworkSuggestion> CREATOR =
@@ -79,7 +89,8 @@
                             in.readParcelable(null), // wifiConfiguration
                             in.readBoolean(), // isAppInteractionRequired
                             in.readBoolean(), // isUserInteractionRequired
-                            in.readInt() // suggestorUid
+                            in.readInt(), // suggestorUid
+                            in.readString() // suggestorPackageName
                     );
                 }
 
@@ -100,12 +111,13 @@
         dest.writeBoolean(isAppInteractionRequired);
         dest.writeBoolean(isUserInteractionRequired);
         dest.writeInt(suggestorUid);
+        dest.writeString(suggestorPackageName);
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
-                wifiConfiguration.allowedKeyManagement, suggestorUid);
+                wifiConfiguration.allowedKeyManagement, suggestorUid, suggestorPackageName);
     }
 
     /**
@@ -124,7 +136,8 @@
                 && Objects.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
                 && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
                                   lhs.wifiConfiguration.allowedKeyManagement)
-                && suggestorUid == lhs.suggestorUid;
+                && suggestorUid == lhs.suggestorUid
+                && TextUtils.equals(suggestorPackageName, lhs.suggestorPackageName);
     }
 
     @Override
@@ -135,6 +148,7 @@
                 .append(", isAppInteractionRequired=").append(isAppInteractionRequired)
                 .append(", isUserInteractionRequired=").append(isUserInteractionRequired)
                 .append(", suggestorUid=").append(suggestorUid)
+                .append(", suggestorPackageName=").append(suggestorPackageName)
                 .append("]");
         return sb.toString();
     }
diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
index 1ee874a..1d499b6 100644
--- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
+++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java
@@ -65,9 +65,9 @@
     public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7;
 
     /**
-     * The reason code for provisioning failure due to invalid server url.
+     * The reason code for provisioning failure due to invalid web url format for an OSU web page.
      */
-    public static final int OSU_FAILURE_INVALID_SERVER_URL = 8;
+    public static final int OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU = 8;
 
     /**
      * The reason code for provisioning failure when a command received is not the expected command
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
index 2258e4d..e6eece8 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
@@ -38,6 +38,8 @@
 public class WifiNetworkAgentSpecifierTest {
     private static final int TEST_UID = 5;
     private static final int TEST_UID_1 = 8;
+    private static final String TEST_PACKAGE = "com.test";
+    private static final String TEST_PACKAGE_1 = "com.test.1";
     private static final String TEST_SSID = "Test123";
     private static final String TEST_SSID_PATTERN = "Test";
     private static final String TEST_SSID_1 = "456test";
@@ -104,14 +106,14 @@
         WifiNetworkAgentSpecifier specifier1 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration1,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
         wifiConfiguration2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkAgentSpecifier specifier2 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration2,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         assertFalse(specifier2.equals(specifier1));
     }
@@ -128,14 +130,14 @@
         WifiNetworkAgentSpecifier specifier1 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration1,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
         wifiConfiguration2.SSID = TEST_SSID_1;
         WifiNetworkAgentSpecifier specifier2 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration2,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         assertFalse(specifier2.equals(specifier1));
     }
@@ -152,14 +154,14 @@
         WifiNetworkAgentSpecifier specifier1 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration1,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
         wifiConfiguration2.BSSID = TEST_BSSID_1;
         WifiNetworkAgentSpecifier specifier2 =
                 new WifiNetworkAgentSpecifier(
                         wifiConfiguration2,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         assertFalse(specifier2.equals(specifier1));
     }
@@ -214,7 +216,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -243,7 +245,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -272,7 +274,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -292,7 +294,7 @@
         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
                 new WifiNetworkAgentSpecifier(
                         wifiConfigurationNetworkAgent,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         PatternMatcher ssidPattern =
                 new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
@@ -305,7 +307,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -325,7 +327,7 @@
         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
                 new WifiNetworkAgentSpecifier(
                         wifiConfigurationNetworkAgent,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         PatternMatcher ssidPattern =
                 new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB);
@@ -339,7 +341,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -359,7 +361,7 @@
         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
                 new WifiNetworkAgentSpecifier(
                         wifiConfigurationNetworkAgent,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE);
 
         PatternMatcher ssidPattern =
                 new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
@@ -373,7 +375,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -401,7 +403,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID);
+                TEST_UID, TEST_PACKAGE);
 
         assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -430,7 +432,7 @@
                 ssidPattern,
                 bssidPattern,
                 wificonfigurationNetworkSpecifier,
-                TEST_UID_1);
+                TEST_UID_1, TEST_PACKAGE_1);
 
         assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
         assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
@@ -446,7 +448,8 @@
     }
 
     private WifiNetworkAgentSpecifier createDefaultNetworkAgentSpecifier() {
-        return new WifiNetworkAgentSpecifier(createDefaultWifiConfiguration(), TEST_UID);
+        return new WifiNetworkAgentSpecifier(createDefaultWifiConfiguration(), TEST_UID,
+                TEST_PACKAGE);
     }
 
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index 2a8df8d..fce247f 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -38,6 +38,7 @@
 @SmallTest
 public class WifiNetworkSpecifierTest {
     private static final int TEST_UID = 5;
+    private static final String TEST_PACKAGE_NAME = "com.test";
     private static final String TEST_SSID = "Test123";
     private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
     private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
@@ -56,7 +57,7 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         Parcel parcelW = Parcel.obtain();
         specifier.writeToParcel(parcelW, 0);
@@ -88,7 +89,7 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         assertTrue(specifier.satisfiedBy(null));
         assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
@@ -111,14 +112,14 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         WifiNetworkSpecifier specifier2 =
                 new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         assertTrue(specifier2.satisfiedBy(specifier1));
     }
@@ -140,7 +141,7 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration1,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
         wifiConfiguration2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
@@ -149,7 +150,7 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration2,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         assertFalse(specifier2.satisfiedBy(specifier1));
     }
@@ -171,14 +172,14 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         WifiNetworkSpecifier specifier2 =
                 new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         assertFalse(specifier2.satisfiedBy(specifier1));
     }
@@ -200,13 +201,42 @@
                         Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
                                 MacAddress.fromString(TEST_BSSID_OUI_MASK)),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
 
         WifiNetworkSpecifier specifier2 =
                 new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
                         Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS),
                         wifiConfiguration,
-                        TEST_UID);
+                        TEST_UID, TEST_PACKAGE_NAME);
+
+        assertFalse(specifier2.satisfiedBy(specifier1));
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create network specifier 1 for WPA_PSK network
+     * b) Create network specifier 2 with different package name .
+     * c) Ensure that the specifier 2 is not satisfied by specifier 1.
+     */
+    @Test
+    public void testWifiNetworkSpecifierDoesNotSatisfyWhenPackageNameDifferent() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+
+        WifiNetworkSpecifier specifier1 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID, TEST_PACKAGE_NAME);
+
+        WifiNetworkSpecifier specifier2 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID, TEST_PACKAGE_NAME + "blah");
 
         assertFalse(specifier2.satisfiedBy(specifier1));
     }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 31f501f..5f76055 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -29,6 +29,10 @@
  */
 @SmallTest
 public class WifiNetworkSuggestionTest {
+    private static final int TEST_UID = 45677;
+    private static final int TEST_UID_OTHER = 45673;
+    private static final String TEST_PACKAGE_NAME = "com.test.packagename";
+    private static final String TEST_PACKAGE_NAME_OTHER = "com.test.packagenameother";
     private static final String TEST_SSID = "\"Test123\"";
     private static final String TEST_BSSID = "12:12:12:12:12:12";
     private static final String TEST_SSID_1 = "\"Test1234\"";
@@ -43,7 +47,7 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, true, 0);
+                new WifiNetworkSuggestion(configuration, false, true, TEST_UID, TEST_PACKAGE_NAME);
 
         Parcel parcelW = Parcel.obtain();
         suggestion.writeToParcel(parcelW, 0);
@@ -77,14 +81,16 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, true, false, 0);
+                new WifiNetworkSuggestion(configuration, true, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.BSSID = TEST_BSSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, true, 0);
+                new WifiNetworkSuggestion(configuration1, false, true, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         assertEquals(suggestion, suggestion1);
     }
@@ -99,13 +105,15 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, 0);
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID_1;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, 0);
+                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
     }
@@ -121,13 +129,15 @@
         configuration.BSSID = TEST_BSSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, 0);
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, 0);
+                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
     }
@@ -142,13 +152,15 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, 0);
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         WifiConfiguration configuration1 = new WifiConfiguration();
         configuration1.SSID = TEST_SSID;
         configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration1, false, false, 0);
+                new WifiNetworkSuggestion(configuration1, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         assertNotEquals(suggestion, suggestion1);
     }
@@ -163,10 +175,31 @@
         configuration.SSID = TEST_SSID;
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
         WifiNetworkSuggestion suggestion =
-                new WifiNetworkSuggestion(configuration, false, false, 0);
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME);
 
         WifiNetworkSuggestion suggestion1 =
-                new WifiNetworkSuggestion(configuration, false, false, 1);
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID_OTHER,
+                        TEST_PACKAGE_NAME);
+
+        assertNotEquals(suggestion, suggestion1);
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
+     * SSID, BSSID and key mgmt, but different package name.
+     */
+    @Test
+    public void testWifiNetworkSuggestionEqualsFailsWhenPackageNameIsDifferent() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID, TEST_PACKAGE_NAME);
+
+        WifiNetworkSuggestion suggestion1 =
+                new WifiNetworkSuggestion(configuration, false, false, TEST_UID,
+                        TEST_PACKAGE_NAME_OTHER);
 
         assertNotEquals(suggestion, suggestion1);
     }