Merge "Replace com.android.internal.util.Preconditions.checkNotNull with java.util.Objects.requireNonNull"
diff --git a/Android.bp b/Android.bp
index 4b82e1d..e1f5abd9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -284,6 +284,7 @@
     name: "framework-aidl-export-defaults",
     aidl: {
         export_include_dirs: [
+            "apex/media/java",
             "core/java",
             "drm/java",
             "graphics/java",
@@ -291,7 +292,6 @@
             "location/java",
             "lowpan/java",
             "media/java",
-            "media/apex/java",
             "media/mca/effect/java",
             "media/mca/filterfw/java",
             "media/mca/filterpacks/java",
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
new file mode 100644
index 0000000..6bd0086
--- /dev/null
+++ b/apex/media/Android.bp
@@ -0,0 +1,120 @@
+// Copyright (C) 2020 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.
+
+java_library {
+    name: "updatable-media",
+
+    srcs: [
+        ":updatable-media-srcs",
+    ],
+
+    aidl: {
+        export_include_dirs: [
+            "java",
+        ],
+
+        // It would be great if we don't need to add include_dirs for public
+        // parcelable classes. Find a better way.
+        include_dirs: [
+            // To refer:
+            // android.os.Bundle
+            // android.os.ResultReceiver
+            "frameworks/base/core/java",
+        ],
+    },
+
+    permitted_packages: [
+        "android.media",
+    ],
+
+    installable: true,
+
+    // TODO: build against stable API surface. Use core_platform for now to avoid
+    // link-check failure with exoplayer building against "current".
+    sdk_version: "core_platform",
+    libs: [
+        // The order matters. android_system_* library should come later.
+        "framework_media_annotation",
+        "android_system_stubs_current",
+    ],
+
+    static_libs: [
+        "exoplayer2-core"
+    ],
+    jarjar_rules: "jarjar_rules.txt",
+
+    plugins: ["java_api_finder"],
+}
+
+filegroup {
+    name: "updatable-media-srcs",
+    srcs: [
+        ":mediaparser-srcs",
+        ":mediasession2-srcs",
+    ],
+}
+
+filegroup {
+    name: "mediasession2-srcs",
+    srcs: [
+        "java/android/media/Controller2Link.java",
+        "java/android/media/IMediaController2.aidl",
+        "java/android/media/IMediaSession2.aidl",
+        "java/android/media/IMediaSession2Service.aidl",
+        "java/android/media/MediaConstants.java",
+        "java/android/media/MediaController2.java",
+        "java/android/media/MediaSession2.java",
+        "java/android/media/MediaSession2Service.java",
+        "java/android/media/Session2Command.java",
+        "java/android/media/Session2CommandGroup.java",
+        "java/android/media/Session2Link.java",
+        "java/android/media/Session2Token.java",
+    ],
+    path: "java",
+}
+
+filegroup {
+    name: "mediaparser-srcs",
+    srcs: [
+        "java/android/media/MediaParser.java"
+    ],
+    path: "java"
+}
+
+droidstubs {
+    name: "updatable-media-stubs",
+    srcs: [
+        ":updatable-media-srcs",
+        ":framework-media-annotation-srcs",
+    ],
+    defaults: [ "framework-module-stubs-defaults-systemapi" ],
+    aidl: {
+        // TODO(b/135922046) remove this
+        include_dirs: ["frameworks/base/core/java"],
+    },
+    sdk_version: "system_current",
+}
+
+java_library {
+    name: "updatable_media_stubs",
+    srcs: [":updatable-media-stubs"],
+    sdk_version: "system_current",
+}
+
+java_library {
+    name: "framework_media_annotation",
+    srcs: [":framework-media-annotation-srcs"],
+    installable: false,
+    sdk_version: "core_current",
+}
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
new file mode 100644
index 0000000..0ac750c
--- /dev/null
+++ b/apex/media/OWNERS
@@ -0,0 +1,4 @@
+andrewlewis@google.com
+dwkang@google.com
+marcone@google.com
+sungsoo@google.com
diff --git a/media/jarjar_rules.txt b/apex/media/jarjar_rules.txt
similarity index 100%
rename from media/jarjar_rules.txt
rename to apex/media/jarjar_rules.txt
diff --git a/media/apex/java/android/media/BufferingParams.java b/apex/media/java/android/media/BufferingParams.java
similarity index 97%
rename from media/apex/java/android/media/BufferingParams.java
rename to apex/media/java/android/media/BufferingParams.java
index 943f142..04af028 100644
--- a/media/apex/java/android/media/BufferingParams.java
+++ b/apex/media/java/android/media/BufferingParams.java
@@ -16,13 +16,9 @@
 
 package android.media;
 
-import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * Structure for source buffering management params.
  *
diff --git a/media/apex/java/android/media/Controller2Link.aidl b/apex/media/java/android/media/Controller2Link.aidl
similarity index 100%
rename from media/apex/java/android/media/Controller2Link.aidl
rename to apex/media/java/android/media/Controller2Link.aidl
diff --git a/media/apex/java/android/media/Controller2Link.java b/apex/media/java/android/media/Controller2Link.java
similarity index 100%
rename from media/apex/java/android/media/Controller2Link.java
rename to apex/media/java/android/media/Controller2Link.java
diff --git a/media/apex/java/android/media/DataSourceCallback.java b/apex/media/java/android/media/DataSourceCallback.java
similarity index 100%
rename from media/apex/java/android/media/DataSourceCallback.java
rename to apex/media/java/android/media/DataSourceCallback.java
diff --git a/media/apex/java/android/media/IMediaController2.aidl b/apex/media/java/android/media/IMediaController2.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaController2.aidl
rename to apex/media/java/android/media/IMediaController2.aidl
diff --git a/media/apex/java/android/media/IMediaSession2.aidl b/apex/media/java/android/media/IMediaSession2.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaSession2.aidl
rename to apex/media/java/android/media/IMediaSession2.aidl
diff --git a/media/apex/java/android/media/IMediaSession2Service.aidl b/apex/media/java/android/media/IMediaSession2Service.aidl
similarity index 100%
rename from media/apex/java/android/media/IMediaSession2Service.aidl
rename to apex/media/java/android/media/IMediaSession2Service.aidl
diff --git a/media/apex/java/android/media/MediaConstants.java b/apex/media/java/android/media/MediaConstants.java
similarity index 100%
rename from media/apex/java/android/media/MediaConstants.java
rename to apex/media/java/android/media/MediaConstants.java
diff --git a/media/apex/java/android/media/MediaController2.java b/apex/media/java/android/media/MediaController2.java
similarity index 100%
rename from media/apex/java/android/media/MediaController2.java
rename to apex/media/java/android/media/MediaController2.java
diff --git a/media/apex/java/android/media/MediaParser.java b/apex/media/java/android/media/MediaParser.java
similarity index 100%
rename from media/apex/java/android/media/MediaParser.java
rename to apex/media/java/android/media/MediaParser.java
diff --git a/media/apex/java/android/media/MediaSession2.java b/apex/media/java/android/media/MediaSession2.java
similarity index 100%
rename from media/apex/java/android/media/MediaSession2.java
rename to apex/media/java/android/media/MediaSession2.java
diff --git a/media/apex/java/android/media/MediaSession2Service.java b/apex/media/java/android/media/MediaSession2Service.java
similarity index 100%
rename from media/apex/java/android/media/MediaSession2Service.java
rename to apex/media/java/android/media/MediaSession2Service.java
diff --git a/media/apex/java/android/media/ProxyDataSourceCallback.java b/apex/media/java/android/media/ProxyDataSourceCallback.java
similarity index 100%
rename from media/apex/java/android/media/ProxyDataSourceCallback.java
rename to apex/media/java/android/media/ProxyDataSourceCallback.java
diff --git a/media/apex/java/android/media/RoutingDelegate.java b/apex/media/java/android/media/RoutingDelegate.java
similarity index 100%
rename from media/apex/java/android/media/RoutingDelegate.java
rename to apex/media/java/android/media/RoutingDelegate.java
diff --git a/media/apex/java/android/media/Session2Command.aidl b/apex/media/java/android/media/Session2Command.aidl
similarity index 100%
rename from media/apex/java/android/media/Session2Command.aidl
rename to apex/media/java/android/media/Session2Command.aidl
diff --git a/media/apex/java/android/media/Session2Command.java b/apex/media/java/android/media/Session2Command.java
similarity index 100%
rename from media/apex/java/android/media/Session2Command.java
rename to apex/media/java/android/media/Session2Command.java
diff --git a/media/apex/java/android/media/Session2CommandGroup.java b/apex/media/java/android/media/Session2CommandGroup.java
similarity index 98%
rename from media/apex/java/android/media/Session2CommandGroup.java
rename to apex/media/java/android/media/Session2CommandGroup.java
index 0ee5f62..13aabfc 100644
--- a/media/apex/java/android/media/Session2CommandGroup.java
+++ b/apex/media/java/android/media/Session2CommandGroup.java
@@ -38,8 +38,8 @@
 public final class Session2CommandGroup implements Parcelable {
     private static final String TAG = "Session2CommandGroup";
 
-    public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup> CREATOR =
-            new Parcelable.Creator<Session2CommandGroup>() {
+    public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup>
+            CREATOR = new Parcelable.Creator<Session2CommandGroup>() {
                 @Override
                 public Session2CommandGroup createFromParcel(Parcel in) {
                     return new Session2CommandGroup(in);
diff --git a/media/apex/java/android/media/Session2Link.java b/apex/media/java/android/media/Session2Link.java
similarity index 100%
rename from media/apex/java/android/media/Session2Link.java
rename to apex/media/java/android/media/Session2Link.java
diff --git a/media/apex/java/android/media/Session2Token.aidl b/apex/media/java/android/media/Session2Token.aidl
similarity index 100%
rename from media/apex/java/android/media/Session2Token.aidl
rename to apex/media/java/android/media/Session2Token.aidl
diff --git a/media/apex/java/android/media/Session2Token.java b/apex/media/java/android/media/Session2Token.java
similarity index 95%
rename from media/apex/java/android/media/Session2Token.java
rename to apex/media/java/android/media/Session2Token.java
index 6eb76b1..aae2e1b 100644
--- a/media/apex/java/android/media/Session2Token.java
+++ b/apex/media/java/android/media/Session2Token.java
@@ -52,17 +52,18 @@
 public final class Session2Token implements Parcelable {
     private static final String TAG = "Session2Token";
 
-    public static final @android.annotation.NonNull Creator<Session2Token> CREATOR = new Creator<Session2Token>() {
-        @Override
-        public Session2Token createFromParcel(Parcel p) {
-            return new Session2Token(p);
-        }
+    public static final @android.annotation.NonNull Creator<Session2Token> CREATOR =
+            new Creator<Session2Token>() {
+                @Override
+                public Session2Token createFromParcel(Parcel p) {
+                    return new Session2Token(p);
+                }
 
-        @Override
-        public Session2Token[] newArray(int size) {
-            return new Session2Token[size];
-        }
-    };
+                @Override
+                public Session2Token[] newArray(int size) {
+                    return new Session2Token[size];
+                }
+            };
 
     /**
      * @hide
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 7ed51ca..e4f7300 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -23,7 +23,6 @@
 import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
 import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
 import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
@@ -1848,7 +1847,7 @@
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
         PowerProfile powerProfile = new PowerProfile(mContext);
-        checkNotNull(powerProfile);
+        Objects.requireNonNull(powerProfile);
 
         StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
                 wallClockNanos);
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
index f3bf909..24b7978 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java
@@ -95,6 +95,12 @@
                 return;
             }
             sStatsd = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
+            if (sStatsd == null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Failed to get stats service.");
+                }
+                return;
+            }
             // Assume statsd is ready since this is called form statscompanion, link to statsd.
             try {
                 sStatsd.asBinder().linkToDeath((IBinder.DeathRecipient) () -> {
diff --git a/api/system-current.txt b/api/system-current.txt
index 405aab3..8a888db 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4099,6 +4099,10 @@
     method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
   }
 
+  public final class AudioRecordingConfiguration implements android.os.Parcelable {
+    method public int getClientUid();
+  }
+
   public class HwAudioSource {
     method public boolean isPlaying();
     method public void start();
@@ -5693,6 +5697,7 @@
   @Deprecated public class WifiConfiguration implements android.os.Parcelable {
     method @Deprecated public int getAuthType();
     method @Deprecated @NonNull public android.net.IpConfiguration.IpAssignment getIpAssignment();
+    method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
     method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus();
     method @Deprecated @NonNull public String getPrintableSsid();
     method @Deprecated @NonNull public android.net.IpConfiguration.ProxySettings getProxySettings();
@@ -9763,6 +9768,7 @@
   }
 
   public class ServiceState implements android.os.Parcelable {
+    method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
     method public int getDataRegistrationState();
     method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
     method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 887d17c..7b96ce9 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -196,18 +196,6 @@
         "libcutils",
         "libstatslog",
     ],
-    target: {
-        android: {
-            shared_libs: [
-                "libutils",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libutils",
-            ],
-        },
-    },
 }
 
 
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index f9f11b2..109785f 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -152,6 +152,10 @@
     return false;
 }
 
+bool HashableDimensionKey::operator!=(const HashableDimensionKey& that) const {
+    return !((*this) == that);
+}
+
 bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
     if (mValues.size() != that.getValues().size()) {
         return false;
diff --git a/cmds/statsd/src/HashableDimensionKey.h b/cmds/statsd/src/HashableDimensionKey.h
index b9b86ce..654e135 100644
--- a/cmds/statsd/src/HashableDimensionKey.h
+++ b/cmds/statsd/src/HashableDimensionKey.h
@@ -71,6 +71,8 @@
 
     std::string toString() const;
 
+    bool operator!=(const HashableDimensionKey& that) const;
+
     bool operator==(const HashableDimensionKey& that) const;
 
     bool operator<(const HashableDimensionKey& that) const;
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 68a51ef..c569bc1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -284,6 +284,10 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 16c936c..6d2bd04 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -85,5 +85,5 @@
 
     optional bool allow_from_any_uid = 50003 [default = false];
 
-    optional string log_from_module = 50004;
-}
\ No newline at end of file
+    optional string module = 50004;
+}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2270974..815e3e6 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -112,9 +112,9 @@
         TouchEventReported touch_event_reported = 34;
         WakeupAlarmOccurred wakeup_alarm_occurred = 35;
         KernelWakeupReported kernel_wakeup_reported = 36;
-        WifiLockStateChanged wifi_lock_state_changed = 37 [(log_from_module) = "wifi"];
-        WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(log_from_module) = "wifi"];
-        WifiScanStateChanged wifi_scan_state_changed = 39 [(log_from_module) = "wifi"];
+        WifiLockStateChanged wifi_lock_state_changed = 37 [(module) = "wifi"];
+        WifiSignalStrengthChanged wifi_signal_strength_changed = 38 [(module) = "wifi"];
+        WifiScanStateChanged wifi_scan_state_changed = 39 [(module) = "wifi"];
         PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
         SettingChanged setting_changed = 41;
         ActivityForegroundStateChanged activity_foreground_state_changed = 42;
@@ -128,7 +128,7 @@
         AppStartFullyDrawn app_start_fully_drawn = 50;
         LmkKillOccurred lmk_kill_occurred = 51;
         PictureInPictureStateChanged picture_in_picture_state_changed = 52;
-        WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(log_from_module) = "wifi"];
+        WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53 [(module) = "wifi"];
         LmkStateChanged lmk_state_changed = 54;
         AppStartMemoryStateCaptured app_start_memory_state_captured = 55;
         ShutdownSequenceReported shutdown_sequence_reported = 56;
@@ -182,39 +182,27 @@
         FlagFlipUpdateOccurred flag_flip_update_occurred = 101;
         BinaryPushStateChanged binary_push_state_changed = 102;
         DevicePolicyEvent device_policy_event = 103;
-        DocsUIFileOperationCanceledReported docs_ui_file_op_canceled =
-            104 [(log_from_module) = "docsui"];
-        DocsUIFileOperationCopyMoveModeReported
-            docs_ui_file_op_copy_move_mode_reported =
-            105 [(log_from_module) = "docsui"];
-        DocsUIFileOperationFailureReported docs_ui_file_op_failure =
-            106 [(log_from_module) = "docsui"];
-        DocsUIFileOperationReported docs_ui_provider_file_op =
-            107 [(log_from_module) = "docsui"];
-        DocsUIInvalidScopedAccessRequestReported
-            docs_ui_invalid_scoped_access_request =
-            108 [(log_from_module) = "docsui"];
-        DocsUILaunchReported docs_ui_launch_reported =
-            109 [(log_from_module) = "docsui"];
-        DocsUIRootVisitedReported docs_ui_root_visited =
-            110 [(log_from_module) = "docsui"];
-        DocsUIStartupMsReported docs_ui_startup_ms =
-            111 [(log_from_module) = "docsui"];
-        DocsUIUserActionReported docs_ui_user_action_reported =
-            112 [(log_from_module) = "docsui"];
+        DocsUIFileOperationCanceledReported docs_ui_file_op_canceled = 104 [(module) = "docsui"];
+        DocsUIFileOperationCopyMoveModeReported docs_ui_file_op_copy_move_mode_reported =
+            105 [(module) = "docsui"];
+        DocsUIFileOperationFailureReported docs_ui_file_op_failure = 106 [(module) = "docsui"];
+        DocsUIFileOperationReported docs_ui_provider_file_op = 107 [(module) = "docsui"];
+        DocsUIInvalidScopedAccessRequestReported docs_ui_invalid_scoped_access_request =
+            108 [(module) = "docsui"];
+        DocsUILaunchReported docs_ui_launch_reported = 109 [(module) = "docsui"];
+        DocsUIRootVisitedReported docs_ui_root_visited = 110 [(module) = "docsui"];
+        DocsUIStartupMsReported docs_ui_startup_ms = 111 [(module) = "docsui"];
+        DocsUIUserActionReported docs_ui_user_action_reported = 112 [(module) = "docsui"];
         WifiEnabledStateChanged wifi_enabled_state_changed = 113;
         WifiRunningStateChanged wifi_running_state_changed = 114;
         AppCompacted app_compacted = 115;
-        NetworkDnsEventReported network_dns_event_reported = 116 [(log_from_module) = "resolv"];
+        NetworkDnsEventReported network_dns_event_reported = 116 [(module) = "resolv"];
         DocsUIPickerLaunchedFromReported docs_ui_picker_launched_from_reported =
-            117 [(log_from_module) = "docsui"];
-        DocsUIPickResultReported docs_ui_pick_result_reported =
-            118 [(log_from_module) = "docsui"];
-        DocsUISearchModeReported docs_ui_search_mode_reported =
-            119 [(log_from_module) = "docsui"];
-        DocsUISearchTypeReported docs_ui_search_type_reported =
-            120 [(log_from_module) = "docsui"];
-        DataStallEvent data_stall_event = 121 [(log_from_module) = "network_stack"];
+            117 [(module) = "docsui"];
+        DocsUIPickResultReported docs_ui_pick_result_reported = 118 [(module) = "docsui"];
+        DocsUISearchModeReported docs_ui_search_mode_reported = 119 [(module) = "docsui"];
+        DocsUISearchTypeReported docs_ui_search_type_reported = 120 [(module) = "docsui"];
+        DataStallEvent data_stall_event = 121 [(module) = "network_stack"];
         RescuePartyResetReported rescue_party_reset_reported = 122;
         SignedConfigReported signed_config_reported = 123;
         GnssNiEventReported gnss_ni_event_reported = 124;
@@ -264,7 +252,7 @@
         ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
         ProcessStartTime process_start_time = 169;
         PermissionGrantRequestResultReported permission_grant_request_result_reported =
-            170 [(log_from_module) = "permissioncontroller"];
+            170 [(module) = "permissioncontroller"];
         BluetoothSocketConnectionStateChanged bluetooth_socket_connection_state_changed = 171;
         DeviceIdentifierAccessDenied device_identifier_access_denied = 172;
         BubbleDeveloperErrorReported bubble_developer_error_reported = 173;
@@ -273,21 +261,21 @@
         AssistGestureProgressReported assist_gesture_progress_reported = 176;
         TouchGestureClassified touch_gesture_classified = 177;
         HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
-        StyleUIChanged style_ui_changed = 179 [(log_from_module) = "style"];
+        StyleUIChanged style_ui_changed = 179 [(module) = "style"];
         PrivacyIndicatorsInteracted privacy_indicators_interacted =
-            180 [(log_from_module) = "permissioncontroller"];
+            180 [(module) = "permissioncontroller"];
         AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
-        NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
+        NetworkStackReported network_stack_reported = 182 [(module) = "network_stack"];
         AppMovedStorageReported app_moved_storage_reported = 183;
         BiometricEnrolled biometric_enrolled = 184;
         SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
         TombStoneOccurred tomb_stone_occurred = 186;
         BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
         IntelligenceEventReported intelligence_event_reported =
-            188 [(log_from_module) = "intelligence"];
+            188 [(module) = "intelligence"];
         ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
         RoleRequestResultReported role_request_result_reported =
-            190 [(log_from_module) = "permissioncontroller"];
+            190 [(module) = "permissioncontroller"];
         MediametricsAudiopolicyReported mediametrics_audiopolicy_reported = 191;
         MediametricsAudiorecordReported mediametrics_audiorecord_reported = 192;
         MediametricsAudiothreadReported mediametrics_audiothread_reported = 193;
@@ -301,36 +289,32 @@
         MediametricsDrmManagerReported mediametrics_drmmanager_reported = 201;
         CarPowerStateChanged car_power_state_changed = 203;
         GarageModeInfo garage_mode_info = 204;
-        TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
+        TestAtomReported test_atom_reported = 205 [(module) = "cts"];
         ContentCaptureCallerMismatchReported content_capture_caller_mismatch_reported = 206;
         ContentCaptureServiceEvents content_capture_service_events = 207;
         ContentCaptureSessionEvents content_capture_session_events = 208;
         ContentCaptureFlushed content_capture_flushed = 209;
         LocationManagerApiUsageReported location_manager_api_usage_reported = 210;
         ReviewPermissionsFragmentResultReported review_permissions_fragment_result_reported =
-            211 [(log_from_module) = "permissioncontroller"];
+            211 [(module) = "permissioncontroller"];
         RuntimePermissionsUpgradeResult runtime_permissions_upgrade_result =
-            212 [(log_from_module) = "permissioncontroller"];
+            212 [(module) = "permissioncontroller"];
         GrantPermissionsActivityButtonActions grant_permissions_activity_button_actions =
-            213 [(log_from_module) = "permissioncontroller"];
+            213 [(module) = "permissioncontroller"];
         LocationAccessCheckNotificationAction location_access_check_notification_action =
-            214 [(log_from_module) = "permissioncontroller"];
+            214 [(module) = "permissioncontroller"];
         AppPermissionFragmentActionReported app_permission_fragment_action_reported =
-            215 [(log_from_module) = "permissioncontroller"];
+            215 [(module) = "permissioncontroller"];
         AppPermissionFragmentViewed app_permission_fragment_viewed =
-            216 [(log_from_module) = "permissioncontroller"];
+            216 [(module) = "permissioncontroller"];
         AppPermissionsFragmentViewed app_permissions_fragment_viewed =
-            217 [(log_from_module) = "permissioncontroller"];
+            217 [(module) = "permissioncontroller"];
         PermissionAppsFragmentViewed permission_apps_fragment_viewed =
-            218  [(log_from_module) = "permissioncontroller"];
-        TextSelectionEvent text_selection_event =
-            219  [(log_from_module) = "textclassifier"];
-        TextLinkifyEvent text_linkify_event =
-            220  [(log_from_module) = "textclassifier"];
-        ConversationActionsEvent conversation_actions_event =
-            221  [(log_from_module) = "textclassifier"];
-        LanguageDetectionEvent language_detection_event =
-            222  [(log_from_module) = "textclassifier"];
+            218  [(module) = "permissioncontroller"];
+        TextSelectionEvent text_selection_event = 219  [(module) = "textclassifier"];
+        TextLinkifyEvent text_linkify_event = 220  [(module) = "textclassifier"];
+        ConversationActionsEvent conversation_actions_event = 221  [(module) = "textclassifier"];
+        LanguageDetectionEvent language_detection_event = 222  [(module) = "textclassifier"];
         ExclusionRectStateChanged exclusion_rect_state_changed = 223;
         BackGesture back_gesture_reported_reported = 224;
         UpdateEngineUpdateAttemptReported update_engine_update_attempt_reported = 225;
@@ -338,21 +322,17 @@
         CameraActionEvent camera_action_event = 227;
         AppCompatibilityChangeReported app_compatibility_change_reported =
             228 [(allow_from_any_uid) = true];
-        PerfettoUploaded perfetto_uploaded =
-            229 [(log_from_module) = "perfetto"];
+        PerfettoUploaded perfetto_uploaded = 229 [(module) = "perfetto"];
         VmsClientConnectionStateChanged vms_client_connection_state_changed = 230;
         GpsLocationStatusReported gps_location_status_reported = 231;
         GpsTimeToFirstFixReported gps_time_to_first_fix_reported = 232;
-        MediaProviderScanEvent media_provider_scan_event =
-            233 [(log_from_module) = "mediaprovider"];
-        MediaProviderDeletionEvent media_provider_deletion_event =
-            234 [(log_from_module) = "mediaprovider"];
+        MediaProviderScanEvent media_provider_scan_event = 233 [(module) = "mediaprovider"];
+        MediaProviderDeletionEvent media_provider_deletion_event = 234 [(module) = "mediaprovider"];
         MediaProviderPermissionEvent media_provider_permission_event =
-            235 [(log_from_module) = "mediaprovider"];
-        MediaProviderSchemaChange media_provider_schema_change =
-            236 [(log_from_module) = "mediaprovider"];
+            235 [(module) = "mediaprovider"];
+        MediaProviderSchemaChange media_provider_schema_change = 236 [(module) = "mediaprovider"];
         MediaProviderIdleMaintenance media_provider_idle_maintenance =
-            237 [(log_from_module) = "mediaprovider"];
+            237 [(module) = "mediaprovider"];
     }
 
     // Pulled events will start at field 10000.
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index c1f95ee..21ffff3 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -277,8 +277,8 @@
 
 void CountMetricProducer::onMatchedLogEventInternalLocked(
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
-        const ConditionKey& conditionKey, bool condition,
-        const LogEvent& event) {
+        const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+        const map<int, HashableDimensionKey>& statePrimaryKeys) {
     int64_t eventTimeNs = event.GetElapsedTimestampNs();
     flushIfNeededLocked(eventTimeNs);
 
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 7b6c7e0..a4711e8 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -59,8 +59,8 @@
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKey, bool condition,
-            const LogEvent& event) override;
+            const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
 
 private:
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index fee5e6e..35c6d37 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -541,8 +541,8 @@
 
 void DurationMetricProducer::onMatchedLogEventInternalLocked(
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
-        const ConditionKey& conditionKeys, bool condition,
-        const LogEvent& event) {
+        const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+        const map<int, HashableDimensionKey>& statePrimaryKeys) {
     ALOGW("Not used in duration tracker.");
 }
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 7457d7f..45908fb 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -59,8 +59,8 @@
 
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKeys, bool condition,
-            const LogEvent& event) override;
+            const ConditionKey& conditionKeys, bool condition, const LogEvent& event,
+            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
 
 private:
     void handleStartEvent(const MetricDimensionKey& eventKey, const ConditionKey& conditionKeys,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 32eb077..6833f8d 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -143,8 +143,8 @@
 
 void EventMetricProducer::onMatchedLogEventInternalLocked(
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
-        const ConditionKey& conditionKey, bool condition,
-        const LogEvent& event) {
+        const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+        const map<int, HashableDimensionKey>& statePrimaryKeys) {
     if (!condition) {
         return;
     }
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index dca37e8..e8f2119 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,8 +47,8 @@
 private:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKey, bool condition,
-            const LogEvent& event) override;
+            const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
 
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 4ab6ec3..4ab6fd4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -449,8 +449,8 @@
 
 void GaugeMetricProducer::onMatchedLogEventInternalLocked(
         const size_t matcherIndex, const MetricDimensionKey& eventKey,
-        const ConditionKey& conditionKey, bool condition,
-        const LogEvent& event) {
+        const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+        const map<int, HashableDimensionKey>& statePrimaryKeys) {
     if (condition == false) {
         return;
     }
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 12dcaa4..284bcc5 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -95,8 +95,8 @@
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKey, bool condition,
-            const LogEvent& event) override;
+            const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
 
 private:
     void onDumpReportLocked(const int64_t dumpTimeNs,
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index cf1d2f3..5c29cb3 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -133,8 +133,8 @@
     HashableDimensionKey dimensionInWhat;
     filterValues(mDimensionsInWhat, event.getValues(), &dimensionInWhat);
     MetricDimensionKey metricKey(dimensionInWhat, stateValuesKey);
-    onMatchedLogEventInternalLocked(
-            matcherIndex, metricKey, conditionKey, condition, event);
+    onMatchedLogEventInternalLocked(matcherIndex, metricKey, conditionKey, condition, event,
+                                    statePrimaryKeys);
 }
 
 bool MetricProducer::evaluateActiveStateLocked(int64_t elapsedTimestampNs) {
@@ -269,6 +269,7 @@
                                          FieldValue* value) {
     if (!StateManager::getInstance().getStateValue(atomId, queryKey, value)) {
         value->mValue = Value(StateTracker::kStateUnknown);
+        value->mField.setTag(atomId);
         ALOGW("StateTracker not found for state atom %d", atomId);
         return;
     }
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 30675fc..99f0c64 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -330,8 +330,8 @@
      */
     virtual void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKey, bool condition,
-            const LogEvent& event) = 0;
+            const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+            const map<int, HashableDimensionKey>& statePrimaryKeys) = 0;
 
     // Consume the parsed stats log entry that already matched the "what" of the metric.
     virtual void onMatchedLogEventLocked(const size_t matcherIndex, const LogEvent& event);
@@ -475,6 +475,10 @@
     FRIEND_TEST(StatsLogProcessorTest,
             TestActivationOnBootMultipleActivationsDifferentActivationTypes);
     FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
+
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 1fda696..6d20822 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -289,6 +289,10 @@
     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
+
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
+    FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index d8f399f..d2db6e9 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -66,6 +66,7 @@
 const int FIELD_ID_DIMENSION_IN_WHAT = 1;
 const int FIELD_ID_BUCKET_INFO = 3;
 const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
+const int FIELD_ID_SLICE_BY_STATE = 6;
 // for ValueBucketInfo
 const int FIELD_ID_VALUE_INDEX = 1;
 const int FIELD_ID_VALUE_LONG = 2;
@@ -146,6 +147,14 @@
         mConditionSliced = true;
     }
 
+    for (const auto& stateLink : metric.state_link()) {
+        Metric2State ms;
+        ms.stateAtomId = stateLink.state_atom_id();
+        translateFieldMatcher(stateLink.fields_in_what(), &ms.metricFields);
+        translateFieldMatcher(stateLink.fields_in_state(), &ms.stateFields);
+        mMetric2StateLinks.push_back(ms);
+    }
+
     int64_t numBucketsForward = calcBucketsForwardCount(startTimeNs);
     mCurrentBucketNum += numBucketsForward;
 
@@ -181,6 +190,33 @@
     }
 }
 
+void ValueMetricProducer::onStateChanged(int64_t eventTimeNs, int32_t atomId,
+                                         const HashableDimensionKey& primaryKey, int oldState,
+                                         int newState) {
+    VLOG("ValueMetric %lld onStateChanged time %lld, State %d, key %s, %d -> %d",
+         (long long)mMetricId, (long long)eventTimeNs, atomId, primaryKey.toString().c_str(),
+         oldState, newState);
+    // If condition is not true, we do not need to pull for this state change.
+    if (mCondition != ConditionState::kTrue) {
+        return;
+    }
+    bool isEventLate = eventTimeNs < mCurrentBucketStartTimeNs;
+    if (isEventLate) {
+        VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
+             (long long)mCurrentBucketStartTimeNs);
+        invalidateCurrentBucket(eventTimeNs, BucketDropReason::EVENT_IN_WRONG_BUCKET);
+        return;
+    }
+    mStateChangePrimaryKey.first = atomId;
+    mStateChangePrimaryKey.second = primaryKey;
+    if (mIsPulled) {
+        pullAndMatchEventsLocked(eventTimeNs);
+    }
+    mStateChangePrimaryKey.first = 0;
+    mStateChangePrimaryKey.second = DEFAULT_DIMENSION_KEY;
+    flushIfNeededLocked(eventTimeNs);
+}
+
 void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition,
                                                            const int64_t eventTime) {
     VLOG("Metric %lld onSlicedConditionMayChange", (long long)mMetricId);
@@ -281,6 +317,14 @@
                                            FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
         }
 
+        // Then fill slice_by_state.
+        for (auto state : dimensionKey.getStateValuesKey().getValues()) {
+            uint64_t stateToken = protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+                                                     FIELD_ID_SLICE_BY_STATE);
+            writeStateToProto(state, protoOutput);
+            protoOutput->end(stateToken);
+        }
+
         // Then fill bucket_info (ValueBucketInfo).
         for (const auto& bucket : pair.second) {
             uint64_t bucketInfoToken = protoOutput->start(
@@ -300,7 +344,7 @@
                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_CONDITION_TRUE_NS,
                                    (long long)bucket.mConditionTrueNs);
             }
-            for (int i = 0; i < (int)bucket.valueIndex.size(); i ++) {
+            for (int i = 0; i < (int)bucket.valueIndex.size(); i++) {
                 int index = bucket.valueIndex[i];
                 const Value& value = bucket.values[i];
                 uint64_t valueToken = protoOutput->start(
@@ -358,9 +402,10 @@
 }
 
 void ValueMetricProducer::resetBase() {
-    for (auto& slice : mCurrentSlicedBucket) {
-        for (auto& interval : slice.second) {
-            interval.hasBase = false;
+    for (auto& slice : mCurrentBaseInfo) {
+        for (auto& baseInfo : slice.second) {
+            baseInfo.hasBase = false;
+            baseInfo.hasCurrentState = false;
         }
     }
     mHasGlobalBase = false;
@@ -558,14 +603,20 @@
             onMatchedLogEventLocked(mWhatMatcherIndex, localCopy);
         }
     }
-    // If the new pulled data does not contains some keys we track in our intervals, we need to
-    // reset the base.
+    // If a key that is:
+    // 1. Tracked in mCurrentSlicedBucket and
+    // 2. A superset of the current mStateChangePrimaryKey
+    // was not found in the new pulled data (i.e. not in mMatchedDimensionInWhatKeys)
+    // then we need to reset the base.
     for (auto& slice : mCurrentSlicedBucket) {
-        bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
-                != mMatchedMetricDimensionKeys.end();
-        if (!presentInPulledData) {
-            for (auto& interval : slice.second) {
-                interval.hasBase = false;
+        const auto& whatKey = slice.first.getDimensionKeyInWhat();
+        bool presentInPulledData =
+                mMatchedMetricDimensionKeys.find(whatKey) != mMatchedMetricDimensionKeys.end();
+        if (!presentInPulledData && whatKey.contains(mStateChangePrimaryKey.second)) {
+            auto it = mCurrentBaseInfo.find(whatKey);
+            for (auto& baseInfo : it->second) {
+                baseInfo.hasBase = false;
+                baseInfo.hasCurrentState = false;
             }
         }
     }
@@ -674,17 +725,30 @@
     return false;
 }
 
-void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIndex,
-                                                          const MetricDimensionKey& eventKey,
-                                                          const ConditionKey& conditionKey,
-                                                          bool condition, const LogEvent& event) {
+void ValueMetricProducer::onMatchedLogEventInternalLocked(
+        const size_t matcherIndex, const MetricDimensionKey& eventKey,
+        const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+        const map<int, HashableDimensionKey>& statePrimaryKeys) {
+    auto whatKey = eventKey.getDimensionKeyInWhat();
+    auto stateKey = eventKey.getStateValuesKey();
+
+    // Skip this event if a state changed occurred for a different primary key.
+    auto it = statePrimaryKeys.find(mStateChangePrimaryKey.first);
+    // Check that both the atom id and the primary key are equal.
+    if (it != statePrimaryKeys.end() && it->second != mStateChangePrimaryKey.second) {
+        VLOG("ValueMetric skip event with primary key %s because state change primary key "
+             "is %s",
+             it->second.toString().c_str(), mStateChangePrimaryKey.second.toString().c_str());
+        return;
+    }
+
     int64_t eventTimeNs = event.GetElapsedTimestampNs();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
         return;
     }
-    mMatchedMetricDimensionKeys.insert(eventKey);
+    mMatchedMetricDimensionKeys.insert(whatKey);
 
     if (!mIsPulled) {
         // We cannot flush without doing a pull first.
@@ -709,10 +773,26 @@
     if (hitGuardRailLocked(eventKey)) {
         return;
     }
-    vector<Interval>& multiIntervals = mCurrentSlicedBucket[eventKey];
-    if (multiIntervals.size() < mFieldMatchers.size()) {
+    vector<BaseInfo>& baseInfos = mCurrentBaseInfo[whatKey];
+    if (baseInfos.size() < mFieldMatchers.size()) {
         VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
-        multiIntervals.resize(mFieldMatchers.size());
+        baseInfos.resize(mFieldMatchers.size());
+    }
+
+    for (auto baseInfo : baseInfos) {
+        if (!baseInfo.hasCurrentState) {
+            baseInfo.currentState = DEFAULT_DIMENSION_KEY;
+            baseInfo.hasCurrentState = true;
+        }
+    }
+
+    // We need to get the intervals stored with the previous state key so we can
+    // close these value intervals.
+    const auto oldStateKey = baseInfos[0].currentState;
+    vector<Interval>& intervals = mCurrentSlicedBucket[MetricDimensionKey(whatKey, oldStateKey)];
+    if (intervals.size() < mFieldMatchers.size()) {
+        VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
+        intervals.resize(mFieldMatchers.size());
     }
 
     // We only use anomaly detection under certain cases.
@@ -725,7 +805,8 @@
 
     for (int i = 0; i < (int)mFieldMatchers.size(); i++) {
         const Matcher& matcher = mFieldMatchers[i];
-        Interval& interval = multiIntervals[i];
+        BaseInfo& baseInfo = baseInfos[i];
+        Interval& interval = intervals[i];
         interval.valueIndex = i;
         Value value;
         if (!getDoubleOrLong(event, matcher, value)) {
@@ -736,60 +817,61 @@
         interval.seenNewData = true;
 
         if (mUseDiff) {
-            if (!interval.hasBase) {
+            if (!baseInfo.hasBase) {
                 if (mHasGlobalBase && mUseZeroDefaultBase) {
                     // The bucket has global base. This key does not.
                     // Optionally use zero as base.
-                    interval.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
-                    interval.hasBase = true;
+                    baseInfo.base = (value.type == LONG ? ZERO_LONG : ZERO_DOUBLE);
+                    baseInfo.hasBase = true;
                 } else {
                     // no base. just update base and return.
-                    interval.base = value;
-                    interval.hasBase = true;
+                    baseInfo.base = value;
+                    baseInfo.hasBase = true;
                     // If we're missing a base, do not use anomaly detection on incomplete data
                     useAnomalyDetection = false;
-                    // Continue (instead of return) here in order to set interval.base and
-                    // interval.hasBase for other intervals
+                    // Continue (instead of return) here in order to set baseInfo.base and
+                    // baseInfo.hasBase for other baseInfos
                     continue;
                 }
             }
+
             Value diff;
             switch (mValueDirection) {
                 case ValueMetric::INCREASING:
-                    if (value >= interval.base) {
-                        diff = value - interval.base;
+                    if (value >= baseInfo.base) {
+                        diff = value - baseInfo.base;
                     } else if (mUseAbsoluteValueOnReset) {
                         diff = value;
                     } else {
                         VLOG("Unexpected decreasing value");
                         StatsdStats::getInstance().notePullDataError(mPullTagId);
-                        interval.base = value;
+                        baseInfo.base = value;
                         // If we've got bad data, do not use anomaly detection
                         useAnomalyDetection = false;
                         continue;
                     }
                     break;
                 case ValueMetric::DECREASING:
-                    if (interval.base >= value) {
-                        diff = interval.base - value;
+                    if (baseInfo.base >= value) {
+                        diff = baseInfo.base - value;
                     } else if (mUseAbsoluteValueOnReset) {
                         diff = value;
                     } else {
                         VLOG("Unexpected increasing value");
                         StatsdStats::getInstance().notePullDataError(mPullTagId);
-                        interval.base = value;
+                        baseInfo.base = value;
                         // If we've got bad data, do not use anomaly detection
                         useAnomalyDetection = false;
                         continue;
                     }
                     break;
                 case ValueMetric::ANY:
-                    diff = value - interval.base;
+                    diff = value - baseInfo.base;
                     break;
                 default:
                     break;
             }
-            interval.base = value;
+            baseInfo.base = value;
             value = diff;
         }
 
@@ -814,12 +896,13 @@
             interval.hasValue = true;
         }
         interval.sampleSize += 1;
+        baseInfo.currentState = stateKey;
     }
 
     // Only trigger the tracker if all intervals are correct
     if (useAnomalyDetection) {
         // TODO: propgate proper values down stream when anomaly support doubles
-        long wholeBucketVal = multiIntervals[0].value.long_value;
+        long wholeBucketVal = intervals[0].value.long_value;
         auto prev = mCurrentFullBucket.find(eventKey);
         if (prev != mCurrentFullBucket.end()) {
             wholeBucketVal += prev->second;
@@ -953,6 +1036,7 @@
         } else {
             it++;
         }
+        // TODO: remove mCurrentBaseInfo entries when obsolete
     }
 
     mCurrentBucketIsInvalid = false;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 4eae99b..19fb694 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -83,11 +83,14 @@
         flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
     };
 
+    void onStateChanged(int64_t eventTimeNs, int32_t atomId, const HashableDimensionKey& primaryKey,
+                        int oldState, int newState) override;
+
 protected:
     void onMatchedLogEventInternalLocked(
             const size_t matcherIndex, const MetricDimensionKey& eventKey,
-            const ConditionKey& conditionKey, bool condition,
-            const LogEvent& event) override;
+            const ConditionKey& conditionKey, bool condition, const LogEvent& event,
+            const std::map<int, HashableDimensionKey>& statePrimaryKeys) override;
 
 private:
     void onDumpReportLocked(const int64_t dumpTimeNs,
@@ -144,7 +147,10 @@
     std::vector<Matcher> mFieldMatchers;
 
     // Value fields for matching.
-    std::set<MetricDimensionKey> mMatchedMetricDimensionKeys;
+    std::set<HashableDimensionKey> mMatchedMetricDimensionKeys;
+
+    // Holds the atom id, primary key pair from a state change.
+    pair<int32_t, HashableDimensionKey> mStateChangePrimaryKey;
 
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
@@ -156,10 +162,6 @@
     typedef struct {
         // Index in multi value aggregation.
         int valueIndex;
-        // Holds current base value of the dimension. Take diff and update if necessary.
-        Value base;
-        // Whether there is a base to diff to.
-        bool hasBase;
         // Current value, depending on the aggregation type.
         Value value;
         // Number of samples collected.
@@ -171,8 +173,21 @@
         bool seenNewData = false;
     } Interval;
 
+    typedef struct {
+        // Holds current base value of the dimension. Take diff and update if necessary.
+        Value base;
+        // Whether there is a base to diff to.
+        bool hasBase;
+        // Last seen state value(s).
+        HashableDimensionKey currentState;
+        // Whether this dimensions in what key has a current state key.
+        bool hasCurrentState;
+    } BaseInfo;
+
     std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
 
+    std::unordered_map<HashableDimensionKey, std::vector<BaseInfo>> mCurrentBaseInfo;
+
     std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
 
     // Save the past buckets and we can clear when the StatsLogReport is dumped.
@@ -285,6 +300,9 @@
     FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
     FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
     FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue);
+    FRIEND_TEST(ValueMetricProducerTest, TestSlicedState);
+    FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithMap);
+    FRIEND_TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions);
     FRIEND_TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey);
     FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBase);
     FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 2ad8217..73c1212 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -18,11 +18,12 @@
 #include "Log.h"
 
 #include "metrics_manager_util.h"
-#include "MetricProducer.h"
 
 #include <inttypes.h>
 
 #include "atoms_info.h"
+#include "FieldValue.h"
+#include "MetricProducer.h"
 #include "condition/CombinationConditionTracker.h"
 #include "condition/SimpleConditionTracker.h"
 #include "condition/StateConditionTracker.h"
@@ -173,6 +174,14 @@
     return true;
 }
 
+bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
+                               const vector<Matcher>& dimensionsInWhat) {
+    vector<Matcher> stateMatchers;
+    translateFieldMatcher(stateMatcher, &stateMatchers);
+
+    return subsetDimensions(stateMatchers, dimensionsInWhat);
+}
+
 // Validates a metricActivation and populates state.
 // EventActivationMap and EventDeactivationMap are supplied to a MetricProducer
 //      to provide the producer with state about its activators and deactivators.
@@ -669,18 +678,41 @@
             }
         }
 
+        std::vector<int> slicedStateAtoms;
+        unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+        if (metric.slice_by_state_size() > 0) {
+            if (!handleMetricWithStates(config, metric.slice_by_state(), stateAtomIdMap,
+                                        allStateGroupMaps, slicedStateAtoms, stateGroupMap)) {
+                return false;
+            }
+        } else {
+            if (metric.state_link_size() > 0) {
+                ALOGW("ValueMetric has a MetricStateLink but doesn't have a sliced state");
+                return false;
+            }
+        }
+
+        // Check that all metric state links are a subset of dimensions_in_what fields.
+        std::vector<Matcher> dimensionsInWhat;
+        translateFieldMatcher(metric.dimensions_in_what(), &dimensionsInWhat);
+        for (const auto& stateLink : metric.state_link()) {
+            if (!handleMetricWithStateLink(stateLink.fields_in_what(), dimensionsInWhat)) {
+                return false;
+            }
+        }
+
         unordered_map<int, shared_ptr<Activation>> eventActivationMap;
         unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
-        bool success = handleMetricActivation(config, metric.id(), metricIndex,
-                metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
-                deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
-                eventDeactivationMap);
+        bool success = handleMetricActivation(
+                config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+                activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+                metricsWithActivation, eventActivationMap, eventDeactivationMap);
         if (!success) return false;
 
         sp<MetricProducer> valueProducer = new ValueMetricProducer(
                 key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
                 timeBaseTimeNs, currentTimeNs, pullerManager, eventActivationMap,
-                eventDeactivationMap);
+                eventDeactivationMap, slicedStateAtoms, stateGroupMap);
         allMetricProducers.push_back(valueProducer);
     }
 
diff --git a/cmds/statsd/src/state/StateManager.cpp b/cmds/statsd/src/state/StateManager.cpp
index 80d3983..ea776fa 100644
--- a/cmds/statsd/src/state/StateManager.cpp
+++ b/cmds/statsd/src/state/StateManager.cpp
@@ -28,13 +28,17 @@
     return sStateManager;
 }
 
+void StateManager::clear() {
+    mStateTrackers.clear();
+}
+
 void StateManager::onLogEvent(const LogEvent& event) {
     if (mStateTrackers.find(event.GetTagId()) != mStateTrackers.end()) {
         mStateTrackers[event.GetTagId()]->onLogEvent(event);
     }
 }
 
-bool StateManager::registerListener(int32_t atomId, wp<StateListener> listener) {
+bool StateManager::registerListener(const int32_t atomId, wp<StateListener> listener) {
     // Check if state tracker already exists.
     if (mStateTrackers.find(atomId) == mStateTrackers.end()) {
         // Create a new state tracker iff atom is a state atom.
@@ -50,7 +54,7 @@
     return true;
 }
 
-void StateManager::unregisterListener(int32_t atomId, wp<StateListener> listener) {
+void StateManager::unregisterListener(const int32_t atomId, wp<StateListener> listener) {
     std::unique_lock<std::mutex> lock(mMutex);
 
     // Hold the sp<> until the lock is released so that ~StateTracker() is
@@ -74,7 +78,7 @@
     lock.unlock();
 }
 
-bool StateManager::getStateValue(int32_t atomId, const HashableDimensionKey& key,
+bool StateManager::getStateValue(const int32_t atomId, const HashableDimensionKey& key,
                                  FieldValue* output) const {
     auto it = mStateTrackers.find(atomId);
     if (it != mStateTrackers.end()) {
diff --git a/cmds/statsd/src/state/StateManager.h b/cmds/statsd/src/state/StateManager.h
index a6053e6..8bc2461 100644
--- a/cmds/statsd/src/state/StateManager.h
+++ b/cmds/statsd/src/state/StateManager.h
@@ -40,30 +40,33 @@
     // Returns a pointer to the single, shared StateManager object.
     static StateManager& getInstance();
 
+    // Unregisters all listeners and removes all trackers from StateManager.
+    void clear();
+
     // Notifies the correct StateTracker of an event.
     void onLogEvent(const LogEvent& event);
 
     // Returns true if atomId is being tracked and is associated with a state
     // atom. StateManager notifies the correct StateTracker to register listener.
     // If the correct StateTracker does not exist, a new StateTracker is created.
-    bool registerListener(int32_t atomId, wp<StateListener> listener);
+    bool registerListener(const int32_t atomId, wp<StateListener> listener);
 
     // Notifies the correct StateTracker to unregister a listener
     // and removes the tracker if it no longer has any listeners.
-    void unregisterListener(int32_t atomId, wp<StateListener> listener);
+    void unregisterListener(const int32_t atomId, wp<StateListener> listener);
 
     // Returns true if the StateTracker exists and queries for the
     // original state value mapped to the given query key. The state value is
     // stored and output in a FieldValue class.
     // Returns false if the StateTracker doesn't exist.
-    bool getStateValue(int32_t atomId, const HashableDimensionKey& queryKey,
+    bool getStateValue(const int32_t atomId, const HashableDimensionKey& queryKey,
                        FieldValue* output) const;
 
     inline int getStateTrackersCount() const {
         return mStateTrackers.size();
     }
 
-    inline int getListenersCount(int32_t atomId) const {
+    inline int getListenersCount(const int32_t atomId) const {
         auto it = mStateTrackers.find(atomId);
         if (it != mStateTrackers.end()) {
             return it->second->getListenersCount();
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 8b4d781..c45274e 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -147,12 +147,14 @@
 message ValueMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+  repeated StateValue slice_by_state = 6;
 
   repeated ValueBucketInfo bucket_info = 3;
 
   repeated DimensionsValue dimension_leaf_values_in_what = 4;
 
+  optional DimensionsValue dimensions_in_condition = 2 [deprecated = true];
+
   repeated DimensionsValue dimension_leaf_values_in_condition = 5 [deprecated = true];
 }
 
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index a22805b..736aa9b 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -290,12 +290,14 @@
 
   optional FieldMatcher dimensions_in_what = 5;
 
-  optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
+  repeated int64 slice_by_state = 18;
 
   optional TimeUnit bucket = 6;
 
   repeated MetricConditionLink links = 7;
 
+  repeated MetricStateLink state_link = 19;
+
   enum AggregationType {
     SUM = 1;
     MIN = 2;
@@ -325,6 +327,8 @@
   optional int32 max_pull_delay_sec = 16 [default = 10];
 
   optional bool split_bucket_for_app_upgrade = 17 [default = true];
+
+  optional FieldMatcher dimensions_in_condition = 9 [deprecated = true];
 }
 
 message Alert {
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 0f51c1b..15fc468 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -27,9 +27,6 @@
 
 #ifdef __ANDROID__
 
-const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
-const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
-
 /**
  * Test a count metric that has one slice_by_state with no primary fields.
  *
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index fb878dc7..e8d2ec5 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -369,6 +369,168 @@
     EXPECT_EQ(1, bucketInfo.values_size());
 }
 
+/**
+ * Test initialization of a simple value metric that is sliced by a state.
+ *
+ * ValueCpuUserTimePerScreenState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState) {
+    // Create config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto pulledAtomMatcher =
+            CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+    *config.add_atom_matcher() = pulledAtomMatcher;
+
+    auto screenState = CreateScreenState();
+    *config.add_state() = screenState;
+
+    // Create value metric that slices by screen state without a map.
+    int64_t metricId = 123456;
+    auto valueMetric = config.add_value_metric();
+    valueMetric->set_id(metricId);
+    valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+    valueMetric->set_what(pulledAtomMatcher.id());
+    *valueMetric->mutable_value_field() =
+            CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+    valueMetric->add_slice_by_state(screenState.id());
+    valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+    // Initialize StatsLogProcessor.
+    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    const uint64_t bucketSizeNs =
+            TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000LL;
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    // Check that ValueMetricProducer was initialized correctly.
+    EXPECT_EQ(1U, processor->mMetricsManagers.size());
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+    EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions) {
+    // Create config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto cpuTimePerUidMatcher =
+            CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+    *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+    auto uidProcessState = CreateUidProcessState();
+    *config.add_state() = uidProcessState;
+
+    // Create value metric that slices by screen state with a complete map.
+    int64_t metricId = 123456;
+    auto valueMetric = config.add_value_metric();
+    valueMetric->set_id(metricId);
+    valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+    valueMetric->set_what(cpuTimePerUidMatcher.id());
+    *valueMetric->mutable_value_field() =
+            CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+    *valueMetric->mutable_dimensions_in_what() =
+            CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+    valueMetric->add_slice_by_state(uidProcessState.id());
+    MetricStateLink* stateLink = valueMetric->add_state_link();
+    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+    *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+    auto fieldsInState = stateLink->mutable_fields_in_state();
+    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+    valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+    // Initialize StatsLogProcessor.
+    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    // Check that StateTrackers were initialized correctly.
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+    // Check that ValueMetricProducer was initialized correctly.
+    EXPECT_EQ(1U, processor->mMetricsManagers.size());
+    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+    EXPECT_TRUE(metricsManager->isConfigValid());
+    EXPECT_EQ(1, metricsManager->mAllMetricProducers.size());
+    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+    EXPECT_EQ(1, metricProducer->mSlicedStateAtoms.size());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, metricProducer->mSlicedStateAtoms.at(0));
+    EXPECT_EQ(0, metricProducer->mStateGroupMap.size());
+}
+
+/**
+ * Test initialization of a value metric that is sliced by state and has
+ * dimensions_in_what.
+ *
+ * ValueCpuUserTimePerUidPerUidProcessState
+ */
+TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions) {
+    // Create config.
+    StatsdConfig config;
+    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+
+    auto cpuTimePerUidMatcher =
+            CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+    *config.add_atom_matcher() = cpuTimePerUidMatcher;
+
+    auto uidProcessState = CreateUidProcessState();
+    *config.add_state() = uidProcessState;
+
+    // Create value metric that slices by screen state with a complete map.
+    int64_t metricId = 123456;
+    auto valueMetric = config.add_value_metric();
+    valueMetric->set_id(metricId);
+    valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+    valueMetric->set_what(cpuTimePerUidMatcher.id());
+    *valueMetric->mutable_value_field() =
+            CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+    valueMetric->add_slice_by_state(uidProcessState.id());
+    MetricStateLink* stateLink = valueMetric->add_state_link();
+    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+    *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+    auto fieldsInState = stateLink->mutable_fields_in_state();
+    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+    valueMetric->set_max_pull_delay_sec(INT_MAX);
+
+    // Initialize StatsLogProcessor.
+    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+    int uid = 12345;
+    int64_t cfgId = 98765;
+    ConfigKey cfgKey(uid, cfgId);
+    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+
+    // No StateTrackers are initialized.
+    EXPECT_EQ(0, StateManager::getInstance().getStateTrackersCount());
+
+    // Config initialization fails.
+    EXPECT_EQ(0, processor->mMetricsManagers.size());
+}
+
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index da0a672..92e8241 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -148,6 +148,26 @@
         return valueProducer;
     }
 
+    static sp<ValueMetricProducer> createValueProducerWithState(
+            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+            vector<int32_t> slicedStateAtoms,
+            unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
+        UidMap uidMap;
+        SimpleAtomMatcher atomMatcher;
+        atomMatcher.set_atom_id(tagId);
+        sp<EventMatcherWizard> eventMatcherWizard =
+                new EventMatcherWizard({new SimpleLogMatchingTracker(
+                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+                kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+                eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+                {}, slicedStateAtoms, stateGroupMap);
+        return valueProducer;
+    }
+
     static ValueMetric createMetric() {
         ValueMetric metric;
         metric.set_id(metricId);
@@ -163,8 +183,13 @@
         metric.set_condition(StringToId("SCREEN_ON"));
         return metric;
     }
-};
 
+    static ValueMetric createMetricWithState(string state) {
+        ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+        metric.add_slice_by_state(StringToId(state));
+        return metric;
+    }
+};
 
 /*
  * Tests that the first bucket works correctly
@@ -253,10 +278,12 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::Interval curInterval =
+            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -273,9 +300,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(23, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(23, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(12, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -294,9 +322,10 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(13, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -394,9 +423,8 @@
             }));
 
     sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-            kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-            logEventMatcherIndex, eventMatcherWizard, tagId,
-            bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+            kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+            eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -411,9 +439,10 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -430,8 +459,8 @@
     // No new data seen, so data has been cleared.
     EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(8, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -447,10 +476,11 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
     // the base was reset
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
@@ -482,9 +512,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -498,8 +529,9 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(10, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(10, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -515,8 +547,9 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(36, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(26, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -549,9 +582,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -565,8 +599,9 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(10, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(10, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -579,8 +614,9 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(36, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(26, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
@@ -633,9 +669,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // startUpdated:false sum:0 start:100
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -652,8 +689,9 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(110, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(110, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(10, curInterval.value.long_value);
 
@@ -663,9 +701,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(20, curInterval.value.long_value);
-    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(false, curBaseInfo.hasBase);
 
     valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
@@ -879,6 +918,7 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
@@ -1066,10 +1106,11 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
 
     // startUpdated:true sum:0 start:11
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(11, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -1084,9 +1125,10 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // tartUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(23, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(23, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
 
@@ -1103,9 +1145,10 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // startUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(36, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
 }
@@ -1148,16 +1191,18 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(false, curBaseInfo.hasBase);
 
     // Now the alarm is delivered.
     // since the condition turned to off before this pull finish, it has no effect
@@ -1167,7 +1212,8 @@
 
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
 }
 
@@ -1220,9 +1266,10 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // startUpdated:false sum:0 start:100
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -1231,15 +1278,17 @@
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
 
     // condition changed to true again, before the pull alarm is delivered
     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(130, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(130, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
 
     // Now the alarm is delivered, but it is considered late, the data will be used
@@ -1249,8 +1298,9 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
 
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(140, curInterval.base.long_value);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(140, curBaseInfo.base.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(10, curInterval.value.long_value);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
@@ -1477,8 +1527,9 @@
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(10, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(10, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
@@ -1497,8 +1548,9 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(15, curInterval.base.long_value);
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(15, curBaseInfo.base.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
     shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
@@ -1508,8 +1560,9 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(15, curInterval.base.long_value);
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(15, curBaseInfo.base.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
@@ -1550,27 +1603,29 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval0 =
-        valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::Interval curInterval1 =
-        valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    EXPECT_EQ(true, curInterval0.hasBase);
-    EXPECT_EQ(10, curInterval0.base.long_value);
-    EXPECT_EQ(false, curInterval0.hasValue);
-    EXPECT_EQ(true, curInterval1.hasBase);
-    EXPECT_EQ(20, curInterval1.base.long_value);
-    EXPECT_EQ(false, curInterval1.hasValue);
+    ValueMetricProducer::Interval curInterval =
+            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(10, curBaseInfo.base.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(20, curBaseInfo.base.long_value);
+    EXPECT_EQ(false, curInterval.hasValue);
 
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    EXPECT_EQ(true, curInterval0.hasValue);
-    EXPECT_EQ(5, curInterval0.value.long_value);
-    EXPECT_EQ(true, curInterval1.hasValue);
-    EXPECT_EQ(2, curInterval1.value.long_value);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(5, curInterval.value.long_value);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(2, curInterval.value.long_value);
 
     // no change in first value field
     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
@@ -1580,14 +1635,17 @@
     event3->init();
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    EXPECT_EQ(true, curInterval0.hasBase);
-    EXPECT_EQ(15, curInterval0.base.long_value);
-    EXPECT_EQ(true, curInterval0.hasValue);
-    EXPECT_EQ(true, curInterval1.hasBase);
-    EXPECT_EQ(25, curInterval1.base.long_value);
-    EXPECT_EQ(true, curInterval1.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(15, curBaseInfo.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(25, curBaseInfo.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
 
     shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
     event4->write(1);
@@ -1596,14 +1654,16 @@
     event4->init();
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    EXPECT_EQ(true, curInterval0.hasBase);
-    EXPECT_EQ(15, curInterval0.base.long_value);
-    EXPECT_EQ(true, curInterval0.hasValue);
-    EXPECT_EQ(true, curInterval1.hasBase);
-    EXPECT_EQ(29, curInterval1.base.long_value);
-    EXPECT_EQ(true, curInterval1.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(15, curBaseInfo.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(29, curBaseInfo.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
 
@@ -1650,9 +1710,11 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto iter = valueProducer->mCurrentSlicedBucket.begin();
     auto& interval1 = iter->second[0];
+    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+    auto& baseInfo1 = iterBase->second[0];
     EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(3, interval1.base.long_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1672,8 +1734,8 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(11, interval1.base.long_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(8, interval1.value.long_value);
 
@@ -1683,11 +1745,19 @@
             break;
         }
     }
+    auto itBase = valueProducer->mCurrentBaseInfo.begin();
+    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+        if (itBase != iterBase) {
+            break;
+        }
+    }
     EXPECT_TRUE(it != iter);
+    EXPECT_TRUE(itBase != iterBase);
     auto& interval2 = it->second[0];
+    auto& baseInfo2 = itBase->second[0];
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(4, interval2.base.long_value);
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(4, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(4, interval2.value.long_value);
 
@@ -1725,11 +1795,13 @@
             ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
 
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto iter = valueProducer->mCurrentSlicedBucket.begin();
-    auto& interval1 = iter->second[0];
-    EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(3, interval1.base.long_value);
+    auto it = valueProducer->mCurrentSlicedBucket.begin();
+    auto& interval1 = it->second[0];
+    auto& baseInfo1 =
+            valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -1749,22 +1821,31 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(11, interval1.base.long_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(8, interval1.value.long_value);
 
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
-        if (it != iter) {
+    auto it2 = valueProducer->mCurrentSlicedBucket.begin();
+    for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
+        if (it2 != it) {
             break;
         }
     }
-    EXPECT_TRUE(it != iter);
-    auto& interval2 = it->second[0];
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(4, interval2.base.long_value);
+    // auto itBase = valueProducer->mCurrentBaseInfo.begin();
+    // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+    //     if (itBase != iterBase) {
+    //         break;
+    //     }
+    // }
+    EXPECT_TRUE(it2 != it);
+    // EXPECT_TRUE(itBase != iterBase);
+    auto& interval2 = it2->second[0];
+    auto& baseInfo2 =
+            valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+    EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(4, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(4, interval2.value.long_value);
     EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1779,8 +1860,8 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
 
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(5, interval2.base.long_value);
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(5, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
     EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1799,17 +1880,24 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
 
     EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0];
-    EXPECT_EQ(true, it1.hasBase);
-    EXPECT_EQ(13, it1.base.long_value);
-    EXPECT_EQ(false, it1.hasValue);
-    EXPECT_EQ(8, it1.value.long_value);
-    auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, it2.hasBase);
-    EXPECT_EQ(5, it2.base.long_value);
-    EXPECT_EQ(false, it2.hasValue);
-    EXPECT_EQ(5, it2.value.long_value);
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
+    interval1 = it->second[0];
+    interval2 = it2->second[0];
+    baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+    baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(5, baseInfo1.base.long_value);
+    EXPECT_EQ(false, interval1.hasValue);
+    EXPECT_EQ(5, interval1.value.long_value);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(13, baseInfo2.base.long_value);
+    EXPECT_EQ(false, interval2.hasValue);
+    EXPECT_EQ(8, interval2.value.long_value);
+
     EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
 }
 
@@ -1839,9 +1927,11 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto iter = valueProducer->mCurrentSlicedBucket.begin();
     auto& interval1 = iter->second[0];
+    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+    auto& baseInfo1 = iterBase->second[0];
     EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(3, interval1.base.long_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(3, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
     vector<shared_ptr<LogEvent>> allData;
@@ -1860,8 +1950,8 @@
 
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, interval1.hasBase);
-    EXPECT_EQ(11, interval1.base.long_value);
+    EXPECT_EQ(true, baseInfo1.hasBase);
+    EXPECT_EQ(11, baseInfo1.base.long_value);
     EXPECT_EQ(false, interval1.hasValue);
     EXPECT_EQ(8, interval1.value.long_value);
     EXPECT_FALSE(interval1.seenNewData);
@@ -1873,11 +1963,19 @@
             break;
         }
     }
+    auto itBase = valueProducer->mCurrentBaseInfo.begin();
+    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+        if (itBase != iterBase) {
+            break;
+        }
+    }
     EXPECT_TRUE(it != iter);
+    EXPECT_TRUE(itBase != iterBase);
     auto& interval2 = it->second[0];
+    auto& baseInfo2 = itBase->second[0];
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(4, interval2.base.long_value);
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(4, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_FALSE(interval2.seenNewData);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1890,12 +1988,13 @@
     event1->init();
     allData.push_back(event1);
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-	// Only one interval left. One was trimmed.
+    // Only one interval left. One was trimmed.
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(5, interval2.base.long_value);
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(5, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_FALSE(interval2.seenNewData);
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
@@ -1909,8 +2008,9 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
 
     interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, interval2.hasBase);
-    EXPECT_EQ(14, interval2.base.long_value);
+    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, baseInfo2.hasBase);
+    EXPECT_EQ(14, baseInfo2.base.long_value);
     EXPECT_EQ(false, interval2.hasValue);
     EXPECT_FALSE(interval2.seenNewData);
     ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
@@ -1946,14 +2046,15 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
 
     vector<shared_ptr<LogEvent>> allData;
     valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
 }
@@ -1983,8 +2084,9 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
 
@@ -1993,7 +2095,7 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
 }
 
@@ -2035,7 +2137,8 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
 }
@@ -2118,8 +2221,9 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(100, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(100, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 }
@@ -2181,8 +2285,9 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(140, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(140, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
@@ -2222,7 +2327,8 @@
             // First onConditionChanged
             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
                 for (int i = 0; i < 2000; i++) {
-                    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+                    shared_ptr<LogEvent> event =
+                            make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
                     event->write(i);
                     event->write(i);
                     event->init();
@@ -2338,8 +2444,9 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(140, curInterval.base.long_value);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(140, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
@@ -2429,7 +2536,8 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
 
@@ -2523,7 +2631,8 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
@@ -2531,7 +2640,8 @@
     valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(false, valueProducer->mHasGlobalBase);
 }
@@ -2579,7 +2689,8 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval& curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
@@ -2589,9 +2700,10 @@
     valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     // Data is empty, base should be reset.
-    EXPECT_EQ(false, curInterval.hasBase);
-    EXPECT_EQ(5, curInterval.base.long_value);
+    EXPECT_EQ(false, curBaseInfo.hasBase);
+    EXPECT_EQ(5, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
 
@@ -2638,12 +2750,14 @@
     // Key 1 should be reset since in not present in the most pull.
     EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
     auto iterator = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(true, iterator->second[0].hasBase);
-    EXPECT_EQ(2, iterator->second[0].base.long_value);
+    auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
+    EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
+    EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
     EXPECT_EQ(false, iterator->second[0].hasValue);
     iterator++;
-    EXPECT_EQ(false, iterator->second[0].hasBase);
-    EXPECT_EQ(1, iterator->second[0].base.long_value);
+    baseInfoIter++;
+    EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
+    EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
     EXPECT_EQ(false, iterator->second[0].hasValue);
 
     EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2715,8 +2829,9 @@
     valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
     ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasBase);
-    EXPECT_EQ(5, curInterval.base.long_value);
+    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(true, curBaseInfo.hasBase);
+    EXPECT_EQ(5, curBaseInfo.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
 
     valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
@@ -2827,6 +2942,7 @@
 
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(2, curInterval.value.long_value);
 
@@ -2918,8 +3034,7 @@
 
     ProtoOutputStream output;
     std::set<string> strSet;
-    valueProducer.onDumpReport(bucketStartTimeNs + 10,
-                               true /* include recent buckets */, true,
+    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
                                FAST, &strSet, &output);
 
     StatsLogReport report = outputStreamToProto(&output);
@@ -2970,9 +3085,8 @@
 
     ProtoOutputStream output;
     std::set<string> strSet;
-    valueProducer.onDumpReport(bucket4StartTimeNs,
-                               false /* include recent buckets */, true,
-                               FAST, &strSet, &output);
+    valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+                               &strSet, &output);
 
     StatsLogReport report = outputStreamToProto(&output);
     // Previous bucket is part of the report.
@@ -3023,8 +3137,7 @@
 
     ProtoOutputStream output;
     std::set<string> strSet;
-    valueProducer.onDumpReport(bucketStartTimeNs + 10,
-                               true /* include recent buckets */, true,
+    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
                                NO_TIME_CONSTRAINTS, &strSet, &output);
 
     StatsLogReport report = outputStreamToProto(&output);
@@ -3058,15 +3171,15 @@
             // condition becomes true
             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(
-                        bucketStartTimeNs + 30, 10));
+                data->push_back(
+                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
                 return true;
             }))
             // condition becomes false
             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(
-                        bucketStartTimeNs + 50, 20));
+                data->push_back(
+                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
                 return true;
             }));
     sp<ValueMetricProducer> valueProducer =
@@ -3079,11 +3192,11 @@
     EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(20, curInterval.value.long_value);
 
-
     // Now the alarm is delivered. Condition is off though.
     vector<shared_ptr<LogEvent>> allData;
     allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
@@ -3091,7 +3204,8 @@
 
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
     curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
 }
 
@@ -3104,8 +3218,8 @@
             // condition becomes true
             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(
-                        bucketStartTimeNs + 30, 10));
+                data->push_back(
+                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
                 return true;
             }));
     sp<ValueMetricProducer> valueProducer =
@@ -3122,7 +3236,8 @@
     assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
     ValueMetricProducer::Interval curInterval =
             valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(false, curInterval.hasBase);
+    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+    EXPECT_EQ(false, curBaseInfo.hasBase);
     EXPECT_EQ(false, curInterval.hasValue);
 }
 
@@ -3153,8 +3268,8 @@
             // condition becomes true
             .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(
-                        bucketStartTimeNs + 30, 10));
+                data->push_back(
+                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
                 return true;
             }))
             .WillOnce(Return(false));
@@ -3768,6 +3883,725 @@
     EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
 }
 
+/*
+ * Test metric with a simple sliced state
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedState) {
+    // Set up ValueMetricProducer.
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // ValueMetricProducer initialized.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write("field1");
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to ON.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+                event->write("field1");
+                event->write(5);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to OFF.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write("field1");
+                event->write(9);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to ON.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+                event->write("field1");
+                event->write(21);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Dump report requested.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+                event->write("field1");
+                event->write(30);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerWithState(
+                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+
+    // Set up StateManager and check that StateTrackers are initialized.
+    StateManager::getInstance().clear();
+    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    // Bucket status after metric initialized.
+    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    auto it = valueProducer->mCurrentSlicedBucket.begin();
+    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(3, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after screen state change kStateUnknown->ON.
+    auto screenEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(5, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change ON->OFF.
+    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+                                                bucketStartTimeNs + 10);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(9, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, ON}
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(4, it->second[0].value.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    it++;
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change OFF->ON.
+    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+                                                bucketStartTimeNs + 15);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(21, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, OFF}
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(12, it->second[0].value.long_value);
+    // Value for dimension, state key {{}, ON}
+    it++;
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(4, it->second[0].value.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    it++;
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Start dump report and check output.
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+                                NO_TIME_CONSTRAINTS, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_TRUE(report.has_value_metrics());
+    EXPECT_EQ(3, report.value_metrics().data_size());
+
+    auto data = report.value_metrics().data(0);
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+    data = report.value_metrics().data(1);
+    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+
+    data = report.value_metrics().data(2);
+    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+    EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+}
+
+/*
+ * Test metric with sliced state with map
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+    // Set up ValueMetricProducer.
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // ValueMetricProducer initialized.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write("field1");
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to ON.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+                event->write("field1");
+                event->write(5);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to VR.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                event->write("field1");
+                event->write(9);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Screen state change to OFF.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+                event->write("field1");
+                event->write(21);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Dump report requested.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+                event->write("field1");
+                event->write(30);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    const StateMap& stateMap = CreateScreenStateOnOffMap();
+    const StateMap_StateGroup screenOnGroup = stateMap.group(0);
+    const StateMap_StateGroup screenOffGroup = stateMap.group(1);
+
+    unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+    for (auto group : stateMap.group()) {
+        for (auto value : group.value()) {
+            stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
+        }
+    }
+
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerWithState(
+                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+
+    // Set up StateManager and check that StateTrackers are initialized.
+    StateManager::getInstance().clear();
+    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+
+    // Bucket status after metric initialized.
+    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    auto it = valueProducer->mCurrentSlicedBucket.begin();
+    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(3, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, {}}
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after screen state change kStateUnknown->ON.
+    auto screenEvent = CreateScreenStateChangedEvent(
+            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(5, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change ON->VR (also ON).
+    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+                                                bucketStartTimeNs + 10);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(9, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, ON GROUP}
+    EXPECT_EQ(screenOnGroup.group_id(),
+              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(4, it->second[0].value.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    it++;
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Bucket status after screen state change VR->OFF.
+    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+                                                bucketStartTimeNs + 15);
+    StateManager::getInstance().onLogEvent(*screenEvent);
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(21, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{}, ON GROUP}
+    EXPECT_EQ(screenOnGroup.group_id(),
+              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(16, it->second[0].value.long_value);
+    // Value for dimension, state key {{}, kStateUnknown}
+    it++;
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Start dump report and check output.
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+                                NO_TIME_CONSTRAINTS, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_TRUE(report.has_value_metrics());
+    EXPECT_EQ(3, report.value_metrics().data_size());
+
+    auto data = report.value_metrics().data(0);
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+
+    data = report.value_metrics().data(1);
+    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+    EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
+
+    data = report.value_metrics().data(2);
+    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+    EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+    EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
+}
+
+/*
+ * Test metric that slices by state with a primary field and has dimensions
+ * - Increasing values
+ * - Using diff
+ * - Second field is value field
+ */
+TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+    // Set up ValueMetricProducer.
+    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+    metric.mutable_dimensions_in_what()->set_field(tagId);
+    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+
+    MetricStateLink* stateLink = metric.add_state_link();
+    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+    *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
+    auto fieldsInState = stateLink->mutable_fields_in_state();
+    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+            // ValueMetricProducer initialized.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(2 /* uid */);
+                event->write(7);
+                event->init();
+                data->push_back(event);
+
+                event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(1 /* uid */);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Uid 1 process state change from kStateUnknown -> Foreground
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+                event->write(1 /* uid */);
+                event->write(6);
+                event->init();
+                data->push_back(event);
+
+                // This event should be skipped.
+                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+                event->write(2 /* uid */);
+                event->write(8);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Uid 2 process state change from kStateUnknown -> Background
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+                event->write(2 /* uid */);
+                event->write(9);
+                event->init();
+                data->push_back(event);
+
+                // This event should be skipped.
+                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+                event->write(1 /* uid */);
+                event->write(12);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Uid 1 process state change from Foreground -> Background
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+                event->write(1 /* uid */);
+                event->write(13);
+                event->init();
+                data->push_back(event);
+
+                // This event should be skipped.
+                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+                event->write(2 /* uid */);
+                event->write(11);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Uid 1 process state change from Background -> Foreground
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+                event->write(1 /* uid */);
+                event->write(17);
+                event->init();
+                data->push_back(event);
+
+                // This event should be skipped.
+                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+                event->write(2 /* uid */);
+                event->write(15);
+                event->init();
+                data->push_back(event);
+                return true;
+            }))
+            // Dump report pull.
+            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+                event->write(2 /* uid */);
+                event->write(20);
+                event->init();
+                data->push_back(event);
+
+                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+                event->write(1 /* uid */);
+                event->write(21);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    sp<ValueMetricProducer> valueProducer =
+            ValueMetricProducerTestHelper::createValueProducerWithState(
+                    pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
+
+    // Set up StateManager and check that StateTrackers are initialized.
+    StateManager::getInstance().clear();
+    StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
+    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+
+    // Bucket status after metric initialized.
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {uid 1}.
+    auto it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(3, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{uid 1}, kStateUnknown}
+    // TODO(tsaichristine): test equality of state values key
+    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+    // Base for dimension key {uid 2}
+    it++;
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(7, itBase->second[0].base.long_value);
+    // Value for dimension, state key {{uid 2}, kStateUnknown}
+    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
+    auto uidProcessEvent = CreateUidProcessStateChangedEvent(
+            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {uid 1}.
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(6, itBase->second[0].base.long_value);
+    // Value for key {uid 1, kStateUnknown}.
+    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(3, it->second[0].value.long_value);
+
+    // Base for dimension key {uid 2}
+    it++;
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(7, itBase->second[0].base.long_value);
+    // Value for key {uid 2, kStateUnknown}
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after uid 2 process state change kStateUnknown -> Background.
+    uidProcessEvent = CreateUidProcessStateChangedEvent(
+            2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+    // Base for dimension key {uid 1}.
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(6, itBase->second[0].base.long_value);
+    // Value for key {uid 1, kStateUnknown}.
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(3, it->second[0].value.long_value);
+
+    // Base for dimension key {uid 2}
+    it++;
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(9, itBase->second[0].base.long_value);
+    // Value for key {uid 2, kStateUnknown}
+    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(2, it->second[0].value.long_value);
+
+    // Pull at end of first bucket.
+    vector<shared_ptr<LogEvent>> allData;
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+    event->write(1 /* uid */);
+    event->write(10);
+    event->init();
+    allData.push_back(event);
+
+    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+    event->write(2 /* uid */);
+    event->write(15);
+    event->init();
+    allData.push_back(event);
+
+    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+    // Buckets flushed after end of first bucket.
+    // None of the buckets should have a value.
+    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    // Base for dimension key {uid 2}.
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(15, itBase->second[0].base.long_value);
+    // Value for key {uid 2, BACKGROUND}.
+    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Base for dimension key {uid 1}
+    it++;
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(10, itBase->second[0].base.long_value);
+    // Value for key {uid 1, kStateUnknown}
+    EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Value for key {uid 1, FOREGROUND}
+    it++;
+    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Value for key {uid 2, kStateUnknown}
+    it++;
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after uid 1 process state change from Foreground -> Background.
+    uidProcessEvent = CreateUidProcessStateChangedEvent(
+            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    // Base for dimension key {uid 2}.
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(15, itBase->second[0].base.long_value);
+    // Value for key {uid 2, BACKGROUND}.
+    EXPECT_EQ(false, it->second[0].hasValue);
+    // Base for dimension key {uid 1}
+    it++;
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(13, itBase->second[0].base.long_value);
+    // Value for key {uid 1, kStateUnknown}
+    EXPECT_EQ(false, it->second[0].hasValue);
+    // Value for key {uid 1, FOREGROUND}
+    it++;
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(3, it->second[0].value.long_value);
+    // Value for key {uid 2, kStateUnknown}
+    it++;
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Bucket status after uid 1 process state change Background->Foreground.
+    uidProcessEvent = CreateUidProcessStateChangedEvent(
+            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+
+    EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+    // Base for dimension key {uid 2}
+    it = valueProducer->mCurrentSlicedBucket.begin();
+    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(true, itBase->second[0].hasBase);
+    EXPECT_EQ(15, itBase->second[0].base.long_value);
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    it++;
+    EXPECT_EQ(false, it->second[0].hasValue);
+
+    // Base for dimension key {uid 1}
+    it++;
+    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+    EXPECT_EQ(17, itBase->second[0].base.long_value);
+    // Value for key {uid 1, BACKGROUND}
+    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(4, it->second[0].value.long_value);
+    // Value for key {uid 1, FOREGROUND}
+    it++;
+    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+    EXPECT_EQ(true, it->second[0].hasValue);
+    EXPECT_EQ(3, it->second[0].value.long_value);
+
+    // Start dump report and check output.
+    ProtoOutputStream output;
+    std::set<string> strSet;
+    valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
+                                NO_TIME_CONSTRAINTS, &strSet, &output);
+
+    StatsLogReport report = outputStreamToProto(&output);
+    EXPECT_TRUE(report.has_value_metrics());
+    EXPECT_EQ(5, report.value_metrics().data_size());
+
+    auto data = report.value_metrics().data(0);
+    EXPECT_EQ(1, data.bucket_info_size());
+    EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+
+    data = report.value_metrics().data(1);
+    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+    EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+
+    data = report.value_metrics().data(2);
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+    EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
+
+    data = report.value_metrics().data(3);
+    EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+    EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
+
+    data = report.value_metrics().data(4);
+    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+    EXPECT_TRUE(data.slice_by_state(0).has_value());
+    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+              data.slice_by_state(0).value());
+    EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+    EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
+    EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index 395167b..26a3733 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -146,6 +146,7 @@
 TEST(StateManagerTest, TestStateManagerGetInstance) {
     sp<TestStateListener> listener1 = new TestStateListener();
     StateManager& mgr = StateManager::getInstance();
+    mgr.clear();
 
     mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
     EXPECT_EQ(1, mgr.getStateTrackersCount());
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 010c194..9bdfeeb 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -30,6 +30,9 @@
 using android::util::ProtoReader;
 using google::protobuf::RepeatedPtrField;
 
+const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
+const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
+
 // Converts a ProtoOutputStream to a StatsLogReport proto.
 StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 08f8734..a4f6f57 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3659,7 +3659,7 @@
                     r.activity, Looper.myLooper());
         }
         r.activity.onGetDirectActions(cancellationSignal, (actions) -> {
-            Preconditions.checkNotNull(actions);
+            Objects.requireNonNull(actions);
             Preconditions.checkCollectionElementsNotNull(actions, "actions");
             if (!actions.isEmpty()) {
                 final int actionCount = actions.size();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 86a5c76..4840963 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -5517,8 +5517,8 @@
     @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
     public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
             @NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) {
-        Preconditions.checkNotNull(executor, "executor cannot be null");
-        Preconditions.checkNotNull(callback, "callback cannot be null");
+        Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
         try {
             mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
                     request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
@@ -5556,8 +5556,8 @@
     @RequiresPermission(Manifest.permission.MANAGE_APPOPS)
     public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request,
             @Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) {
-        Preconditions.checkNotNull(executor, "executor cannot be null");
-        Preconditions.checkNotNull(callback, "callback cannot be null");
+        Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
         try {
             mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
                     request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
@@ -7062,7 +7062,7 @@
         private final IAppOpsAsyncNotedCallback mAsyncCb = new IAppOpsAsyncNotedCallback.Stub() {
             @Override
             public void opNoted(AsyncNotedAppOp op) {
-                Preconditions.checkNotNull(op);
+                Objects.requireNonNull(op);
 
                 getAsyncNotedExecutor().execute(() -> onAsyncNoted(op));
             }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7f26565..1c6a561 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -100,7 +100,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.util.Preconditions;
 import com.android.internal.util.UserIcons;
 
 import dalvik.system.VMRuntime;
@@ -2149,7 +2148,7 @@
             } else if (vol.isPrimaryPhysical()) {
                 volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
             } else {
-                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
+                volumeUuid = Objects.requireNonNull(vol.fsUuid);
             }
 
             return mPM.movePackage(packageName, volumeUuid);
@@ -2259,7 +2258,7 @@
             } else if (vol.isPrimaryPhysical()) {
                 volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
             } else {
-                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
+                volumeUuid = Objects.requireNonNull(vol.fsUuid);
             }
 
             return mPM.movePrimaryStorage(volumeUuid);
@@ -2661,8 +2660,8 @@
     /** @hide */
     @Override
     public KeySet getKeySetByAlias(String packageName, String alias) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(alias);
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(alias);
         try {
             return mPM.getKeySetByAlias(packageName, alias);
         } catch (RemoteException e) {
@@ -2673,7 +2672,7 @@
     /** @hide */
     @Override
     public KeySet getSigningKeySet(String packageName) {
-        Preconditions.checkNotNull(packageName);
+        Objects.requireNonNull(packageName);
         try {
             return mPM.getSigningKeySet(packageName);
         } catch (RemoteException e) {
@@ -2684,8 +2683,8 @@
     /** @hide */
     @Override
     public boolean isSignedBy(String packageName, KeySet ks) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(ks);
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(ks);
         try {
             return mPM.isPackageSignedByKeySet(packageName, ks);
         } catch (RemoteException e) {
@@ -2696,8 +2695,8 @@
     /** @hide */
     @Override
     public boolean isSignedByExactly(String packageName, KeySet ks) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(ks);
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(ks);
         try {
             return mPM.isPackageSignedByKeySetExactly(packageName, ks);
         } catch (RemoteException e) {
diff --git a/core/java/android/app/AuthenticationRequiredException.java b/core/java/android/app/AuthenticationRequiredException.java
index 0d87336..847d2c4 100644
--- a/core/java/android/app/AuthenticationRequiredException.java
+++ b/core/java/android/app/AuthenticationRequiredException.java
@@ -21,7 +21,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
 
 /**
  * Specialization of {@link SecurityException} that is thrown when authentication is needed from the
@@ -60,7 +60,7 @@
      */
     public AuthenticationRequiredException(Throwable cause, PendingIntent userAction) {
         super(cause.getMessage());
-        mUserAction = Preconditions.checkNotNull(userAction);
+        mUserAction = Objects.requireNonNull(userAction);
     }
 
     /**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bd87fcd..cd84310 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2794,7 +2794,7 @@
 
         public ApplicationContentResolver(Context context, ActivityThread mainThread) {
             super(context);
-            mMainThread = Preconditions.checkNotNull(mainThread);
+            mMainThread = Objects.requireNonNull(mainThread);
         }
 
         @Override
diff --git a/core/java/android/app/DirectAction.java b/core/java/android/app/DirectAction.java
index ef3627b..0268f7c 100644
--- a/core/java/android/app/DirectAction.java
+++ b/core/java/android/app/DirectAction.java
@@ -172,7 +172,7 @@
          *     current application state.
          */
         public Builder(@NonNull String id) {
-            Preconditions.checkNotNull(id);
+            Objects.requireNonNull(id);
             mId = id;
         }
 
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 453c600..775b1d1 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -46,7 +46,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.sysprop.ProductProperties;
+import android.sysprop.VndkProperties;
 import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -785,13 +785,12 @@
         // Similar to vendor apks, we should add /product/lib for apks from product partition
         // when product apps are marked as unbundled. We cannot use the same way from vendor
         // to check if lib path exists because there is possibility that /product/lib would not
-        // exist from legacy device while product apks are bundled. To make this clear, new
-        // property ("ro.product.apps.unbundled") is defined which should be true only when
-        // product apks are unbundled.
+        // exist from legacy device while product apks are bundled. To make this clear, we use
+        // "ro.product.vndk.version" property. If the property is defined, we regard all product
+        // apks as unbundled.
         if (mApplicationInfo.getCodePath() != null
-                && mApplicationInfo.isProduct() && ProductProperties.unbundled_apps().orElse(false)
-                // TODO(b/128557860): Change target SDK version when version code R is available.
-                && getTargetSdkVersion() == Build.VERSION_CODES.CUR_DEVELOPMENT) {
+                && mApplicationInfo.isProduct()
+                && VndkProperties.product_vndk_version().isPresent()) {
             isBundledApp = false;
         }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 31c73b9..ca3d0d7 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -198,6 +198,7 @@
 import com.android.internal.util.Preconditions;
 
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Manages all of the system services that can be returned by {@link Context#getSystemService}.
@@ -1429,8 +1430,8 @@
             @NonNull StaticServiceProducerWithBinder<TServiceClass> serviceProducer) {
         ensureInitializing("registerStaticService");
         Preconditions.checkStringNotEmpty(serviceName);
-        Preconditions.checkNotNull(serviceWrapperClass);
-        Preconditions.checkNotNull(serviceProducer);
+        Objects.requireNonNull(serviceWrapperClass);
+        Objects.requireNonNull(serviceProducer);
 
         registerService(serviceName, serviceWrapperClass,
                 new StaticServiceFetcher<TServiceClass>() {
@@ -1453,8 +1454,8 @@
             @NonNull StaticServiceProducerWithoutBinder<TServiceClass> serviceProducer) {
         ensureInitializing("registerStaticService");
         Preconditions.checkStringNotEmpty(serviceName);
-        Preconditions.checkNotNull(serviceWrapperClass);
-        Preconditions.checkNotNull(serviceProducer);
+        Objects.requireNonNull(serviceWrapperClass);
+        Objects.requireNonNull(serviceProducer);
 
         registerService(serviceName, serviceWrapperClass,
                 new StaticServiceFetcher<TServiceClass>() {
@@ -1486,8 +1487,8 @@
             @NonNull ContextAwareServiceProducerWithBinder<TServiceClass> serviceProducer) {
         ensureInitializing("registerContextAwareService");
         Preconditions.checkStringNotEmpty(serviceName);
-        Preconditions.checkNotNull(serviceWrapperClass);
-        Preconditions.checkNotNull(serviceProducer);
+        Objects.requireNonNull(serviceWrapperClass);
+        Objects.requireNonNull(serviceProducer);
 
         registerService(serviceName, serviceWrapperClass,
                 new CachedServiceFetcher<TServiceClass>() {
@@ -1514,8 +1515,8 @@
             @NonNull ContextAwareServiceProducerWithoutBinder<TServiceClass> serviceProducer) {
         ensureInitializing("registerContextAwareService");
         Preconditions.checkStringNotEmpty(serviceName);
-        Preconditions.checkNotNull(serviceWrapperClass);
-        Preconditions.checkNotNull(serviceProducer);
+        Objects.requireNonNull(serviceWrapperClass);
+        Objects.requireNonNull(serviceProducer);
 
         registerService(serviceName, serviceWrapperClass,
                 new CachedServiceFetcher<TServiceClass>() {
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index b37120f..c262ec2 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -44,6 +44,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -1129,8 +1130,8 @@
      */
     public boolean registerOnDestroyedCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull Runnable callback) {
-        Preconditions.checkNotNull(executor);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
         if (isDestroyed()) {
             Log.w(TAG, "Cannot interact with a destroyed voice interactor");
             return false;
@@ -1146,7 +1147,7 @@
      * @return whether the callback was unregistered.
      */
     public boolean unregisterOnDestroyedCallback(@NonNull Runnable callback) {
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(callback);
         if (isDestroyed()) {
             Log.w(TAG, "Cannot interact with a destroyed voice interactor");
             return false;
diff --git a/core/java/android/app/admin/DevicePolicyEventLogger.java b/core/java/android/app/admin/DevicePolicyEventLogger.java
index 95a7973..4c0e176 100644
--- a/core/java/android/app/admin/DevicePolicyEventLogger.java
+++ b/core/java/android/app/admin/DevicePolicyEventLogger.java
@@ -25,6 +25,7 @@
 import com.android.internal.util.Preconditions;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * A wrapper for logging managed device events using {@link StatsLog}.
@@ -136,7 +137,7 @@
      * in that order.
      */
     public DevicePolicyEventLogger setStrings(String value, String[] values) {
-        Preconditions.checkNotNull(values, "values parameter cannot be null");
+        Objects.requireNonNull(values, "values parameter cannot be null");
         mStringArrayValue = new String[values.length + 1];
         mStringArrayValue[0] = value;
         System.arraycopy(values, 0, mStringArrayValue, 1, values.length);
@@ -150,7 +151,7 @@
      * and <code>values</code>, in that order.
      */
     public DevicePolicyEventLogger setStrings(String value1, String value2, String[] values) {
-        Preconditions.checkNotNull(values, "values parameter cannot be null");
+        Objects.requireNonNull(values, "values parameter cannot be null");
         mStringArrayValue = new String[values.length + 2];
         mStringArrayValue[0] = value1;
         mStringArrayValue[1] = value2;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index acdf919..8daaaaa 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -115,6 +115,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -4263,7 +4264,7 @@
      *            {@link #WIPE_SILENTLY} is set.
      */
     public void wipeData(int flags, @NonNull CharSequence reason) {
-        Preconditions.checkNotNull(reason, "reason string is null");
+        Objects.requireNonNull(reason, "reason string is null");
         Preconditions.checkStringNotEmpty(reason, "reason string is empty");
         Preconditions.checkArgument((flags & WIPE_SILENTLY) == 0, "WIPE_SILENTLY cannot be set");
         wipeDataInternal(flags, reason.toString());
@@ -10430,8 +10431,8 @@
             @NonNull String packageName, @NonNull @CallbackExecutor Executor executor,
             @NonNull OnClearApplicationUserDataListener listener) {
         throwIfParentInstance("clearAppData");
-        Preconditions.checkNotNull(executor);
-        Preconditions.checkNotNull(listener);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(listener);
         try {
             mService.clearApplicationUserData(admin, packageName,
                     new IPackageDataObserver.Stub() {
@@ -10881,7 +10882,7 @@
     @WorkerThread public @PrivateDnsModeErrorCodes int setGlobalPrivateDnsModeSpecifiedHost(
             @NonNull ComponentName admin, @NonNull String privateDnsHost) {
         throwIfParentInstance("setGlobalPrivateDnsModeSpecifiedHost");
-        Preconditions.checkNotNull(privateDnsHost, "dns resolver is null");
+        Objects.requireNonNull(privateDnsHost, "dns resolver is null");
 
         if (mService == null) {
             return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 80c5b17..22d8c87 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -41,6 +41,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * <p>This API automatically creates assist data from the platform's
@@ -1889,7 +1890,7 @@
 
         @Override
         public void setTextIdEntry(@NonNull String entryName) {
-            mNode.mTextIdEntry = Preconditions.checkNotNull(entryName);
+            mNode.mTextIdEntry = Objects.requireNonNull(entryName);
         }
 
         @Override
@@ -1899,7 +1900,7 @@
 
         @Override
         public void setHintIdEntry(@NonNull String entryName) {
-            mNode.mHintIdEntry = Preconditions.checkNotNull(entryName);
+            mNode.mHintIdEntry = Objects.requireNonNull(entryName);
         }
 
         @Override
diff --git a/core/java/android/app/prediction/AppPredictionManager.java b/core/java/android/app/prediction/AppPredictionManager.java
index cb5b7e7..ca22721 100644
--- a/core/java/android/app/prediction/AppPredictionManager.java
+++ b/core/java/android/app/prediction/AppPredictionManager.java
@@ -20,7 +20,7 @@
 import android.annotation.TestApi;
 import android.content.Context;
 
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
 
 /**
  * Class that provides methods to create prediction clients.
@@ -37,7 +37,7 @@
      * @hide
      */
     public AppPredictionManager(Context context) {
-        mContext = Preconditions.checkNotNull(context);
+        mContext = Objects.requireNonNull(context);
     }
 
     /**
diff --git a/core/java/android/app/prediction/AppTarget.java b/core/java/android/app/prediction/AppTarget.java
index 6f21490..14e32b83 100644
--- a/core/java/android/app/prediction/AppTarget.java
+++ b/core/java/android/app/prediction/AppTarget.java
@@ -25,7 +25,7 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 
-import com.android.internal.util.Preconditions;
+import java.util.Objects;
 
 /**
  * A representation of a launchable target.
@@ -55,9 +55,9 @@
         mId = id;
         mShortcutInfo = null;
 
-        mPackageName = Preconditions.checkNotNull(packageName);
+        mPackageName = Objects.requireNonNull(packageName);
         mClassName = className;
-        mUser = Preconditions.checkNotNull(user);
+        mUser = Objects.requireNonNull(user);
         mRank = 0;
     }
 
@@ -69,7 +69,7 @@
     public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo,
             @Nullable String className) {
         mId = id;
-        mShortcutInfo = Preconditions.checkNotNull(shortcutInfo);
+        mShortcutInfo = Objects.requireNonNull(shortcutInfo);
 
         mPackageName = mShortcutInfo.getPackage();
         mUser = mShortcutInfo.getUserHandle();
@@ -224,9 +224,9 @@
         @TestApi
         public Builder(@NonNull AppTargetId id, @NonNull String packageName,
                 @NonNull UserHandle user) {
-            mId = Preconditions.checkNotNull(id);
-            mPackageName = Preconditions.checkNotNull(packageName);
-            mUser = Preconditions.checkNotNull(user);
+            mId = Objects.requireNonNull(id);
+            mPackageName = Objects.requireNonNull(packageName);
+            mUser = Objects.requireNonNull(user);
         }
 
         /**
@@ -237,8 +237,8 @@
         @SystemApi
         @TestApi
         public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
-            mId = Preconditions.checkNotNull(id);
-            mShortcutInfo = Preconditions.checkNotNull(info);
+            mId = Objects.requireNonNull(id);
+            mShortcutInfo = Objects.requireNonNull(info);
             mPackageName = info.getPackage();
             mUser = info.getUserHandle();
         }
@@ -253,8 +253,8 @@
             if (mPackageName != null) {
                 throw new IllegalArgumentException("Target is already set");
             }
-            mPackageName = Preconditions.checkNotNull(packageName);
-            mUser = Preconditions.checkNotNull(user);
+            mPackageName = Objects.requireNonNull(packageName);
+            mUser = Objects.requireNonNull(user);
             return this;
         }
 
@@ -266,7 +266,7 @@
         @Deprecated
         public Builder setTarget(@NonNull ShortcutInfo info) {
             setTarget(info.getPackage(), info.getUserHandle());
-            mShortcutInfo = Preconditions.checkNotNull(info);
+            mShortcutInfo = Objects.requireNonNull(info);
             return this;
         }
 
@@ -275,7 +275,7 @@
          */
         @NonNull
         public Builder setClassName(@NonNull String className) {
-            mClassName = Preconditions.checkNotNull(className);
+            mClassName = Objects.requireNonNull(className);
             return this;
         }
 
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index a7319f6..823fdd2 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -28,7 +28,6 @@
 import android.os.Parcelable;
 
 import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -428,7 +427,7 @@
          * @see SliceItem#getSubType()
          */
         public Builder addSubSlice(@NonNull Slice slice, @Nullable @SliceSubtype String subType) {
-            Preconditions.checkNotNull(slice);
+            Objects.requireNonNull(slice);
             mItems.add(new SliceItem(slice, SliceItem.FORMAT_SLICE, subType,
                     slice.getHints().toArray(new String[slice.getHints().size()])));
             return this;
@@ -441,8 +440,8 @@
          */
         public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s,
                 @Nullable @SliceSubtype String subType) {
-            Preconditions.checkNotNull(action);
-            Preconditions.checkNotNull(s);
+            Objects.requireNonNull(action);
+            Objects.requireNonNull(s);
             List<String> hints = s.getHints();
             s.mSpec = null;
             mItems.add(new SliceItem(action, s, SliceItem.FORMAT_ACTION, subType, hints.toArray(
@@ -468,7 +467,7 @@
          */
         public Builder addIcon(Icon icon, @Nullable @SliceSubtype String subType,
                 @SliceHint List<String> hints) {
-            Preconditions.checkNotNull(icon);
+            Objects.requireNonNull(icon);
             mItems.add(new SliceItem(icon, SliceItem.FORMAT_IMAGE, subType, hints));
             return this;
         }
@@ -481,7 +480,7 @@
         public Slice.Builder addRemoteInput(RemoteInput remoteInput,
                 @Nullable @SliceSubtype String subType,
                 @SliceHint List<String> hints) {
-            Preconditions.checkNotNull(remoteInput);
+            Objects.requireNonNull(remoteInput);
             mItems.add(new SliceItem(remoteInput, SliceItem.FORMAT_REMOTE_INPUT,
                     subType, hints));
             return this;
@@ -529,7 +528,7 @@
          */
         public Slice.Builder addBundle(Bundle bundle, @Nullable @SliceSubtype String subType,
                 @SliceHint List<String> hints) {
-            Preconditions.checkNotNull(bundle);
+            Objects.requireNonNull(bundle);
             mItems.add(new SliceItem(bundle, SliceItem.FORMAT_BUNDLE, subType,
                     hints));
             return this;
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 90ecce2..4da1acb 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -51,6 +51,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -241,7 +242,7 @@
      * @see Slice
      */
     public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull Set<SliceSpec> supportedSpecs) {
-        Preconditions.checkNotNull(uri, "uri");
+        Objects.requireNonNull(uri, "uri");
         ContentResolver resolver = mContext.getContentResolver();
         try (ContentProviderClient provider = resolver.acquireUnstableContentProviderClient(uri)) {
             if (provider == null) {
@@ -336,7 +337,7 @@
     }
 
     private Uri resolveStatic(@NonNull Intent intent, ContentResolver resolver) {
-        Preconditions.checkNotNull(intent, "intent");
+        Objects.requireNonNull(intent, "intent");
         Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
                 || intent.getData() != null,
                 "Slice intent must be explicit %s", intent);
@@ -371,7 +372,7 @@
      */
     public @Nullable Slice bindSlice(@NonNull Intent intent,
             @NonNull Set<SliceSpec> supportedSpecs) {
-        Preconditions.checkNotNull(intent, "intent");
+        Objects.requireNonNull(intent, "intent");
         Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null
                 || intent.getData() != null,
                 "Slice intent must be explicit %s", intent);
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 7412970..4346d97 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -16,8 +16,6 @@
 
 package android.app.usage;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -42,6 +40,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.Objects;
+
 /**
  * Provides access to network usage history and statistics. Usage data is collected in
  * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -418,7 +418,7 @@
     /** @hide */
     public void registerUsageCallback(NetworkTemplate template, int networkType,
             long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
-        checkNotNull(callback, "UsageCallback cannot be null");
+        Objects.requireNonNull(callback, "UsageCallback cannot be null");
 
         final Looper looper;
         if (handler == null) {
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index eecf092..1ef1563 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -63,8 +63,8 @@
 
     /** {@hide} */
     public StorageStatsManager(Context context, IStorageStatsManager service) {
-        mContext = Preconditions.checkNotNull(context);
-        mService = Preconditions.checkNotNull(service);
+        mContext = Objects.requireNonNull(context);
+        mService = Objects.requireNonNull(service);
     }
 
     /** {@hide} */
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 83eaa72..38498bc 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -472,63 +472,6 @@
     }
 
     /**
-     * Get the volume of the device.
-     *
-     * <p> The volume is between -128 dB (mute) to 0 dB.
-     *
-     * @return volume of the hearing aid device.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public int getVolume() {
-        if (VDBG) {
-            log("getVolume()");
-        }
-        final IBluetoothHearingAid service = getService();
-        try {
-            if (service != null && isEnabled()) {
-                return service.getVolume();
-            }
-            if (service == null) Log.w(TAG, "Proxy not attached to service");
-            return 0;
-        } catch (RemoteException e) {
-            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return 0;
-        }
-    }
-
-    /**
-     * Tells remote device to adjust volume. Uses the following values:
-     * <ul>
-     * <li>{@link AudioManager#ADJUST_LOWER}</li>
-     * <li>{@link AudioManager#ADJUST_RAISE}</li>
-     * <li>{@link AudioManager#ADJUST_MUTE}</li>
-     * <li>{@link AudioManager#ADJUST_UNMUTE}</li>
-     * </ul>
-     *
-     * @param direction One of the supported adjust values.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public void adjustVolume(int direction) {
-        if (DBG) log("adjustVolume(" + direction + ")");
-
-        final IBluetoothHearingAid service = getService();
-        try {
-            if (service == null) {
-                Log.w(TAG, "Proxy not attached to service");
-                return;
-            }
-
-            if (!isEnabled()) return;
-
-            service.adjustVolume(direction);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-        }
-    }
-
-    /**
      * Tells remote device to set an absolute volume.
      *
      * @param volume Absolute volume to be set on remote
diff --git a/core/java/android/content/pm/VersionedPackage.java b/core/java/android/content/pm/VersionedPackage.java
index 3e22eb2..21df7ec 100644
--- a/core/java/android/content/pm/VersionedPackage.java
+++ b/core/java/android/content/pm/VersionedPackage.java
@@ -96,6 +96,20 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        return o instanceof VersionedPackage
+                && ((VersionedPackage) o).mPackageName.equals(mPackageName)
+                && ((VersionedPackage) o).mVersionCode == mVersionCode;
+    }
+
+    @Override
+    public int hashCode() {
+        // Roll our own hash function without using Objects#hash which incurs the overhead
+        // of autoboxing.
+        return 31 * mPackageName.hashCode() + Long.hashCode(mVersionCode);
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index c89796d..6378db0 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -88,6 +89,11 @@
     private final SparseLongArray mCeSnapshotInodes;
 
     /**
+     * The userdata policy to execute when a rollback for this package is committed.
+     */
+    private final int mRollbackDataPolicy;
+
+    /**
      * Returns the name of the package to roll back from.
      */
     @NonNull
@@ -148,6 +154,11 @@
     }
 
     /** @hide */
+    public @PackageManager.RollbackDataPolicy int getRollbackDataPolicy() {
+        return mRollbackDataPolicy;
+    }
+
+    /** @hide */
     public IntArray getSnapshottedUsers() {
         return mSnapshottedUsers;
     }
@@ -181,11 +192,23 @@
             @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
             boolean isApex, @NonNull IntArray snapshottedUsers,
             @NonNull SparseLongArray ceSnapshotInodes) {
+        this(packageRolledBackFrom, packageRolledBackTo, pendingBackups, pendingRestores, isApex,
+                snapshottedUsers, ceSnapshotInodes, PackageManager.RollbackDataPolicy.RESTORE);
+    }
+
+    /** @hide */
+    public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
+            VersionedPackage packageRolledBackTo,
+            @NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
+            boolean isApex, @NonNull IntArray snapshottedUsers,
+            @NonNull SparseLongArray ceSnapshotInodes,
+            @PackageManager.RollbackDataPolicy int rollbackDataPolicy) {
         this.mVersionRolledBackFrom = packageRolledBackFrom;
         this.mVersionRolledBackTo = packageRolledBackTo;
         this.mPendingBackups = pendingBackups;
         this.mPendingRestores = pendingRestores;
         this.mIsApex = isApex;
+        this.mRollbackDataPolicy = rollbackDataPolicy;
         this.mSnapshottedUsers = snapshottedUsers;
         this.mCeSnapshotInodes = ceSnapshotInodes;
     }
@@ -198,6 +221,7 @@
         this.mPendingBackups = null;
         this.mSnapshottedUsers = null;
         this.mCeSnapshotInodes = null;
+        this.mRollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
     }
 
     @Override
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 7e1506f..4c114fd 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -90,19 +90,19 @@
          * @hide
          */
         @SystemApi
-        int EMPTY_SET = 0x0;
+        int EMPTY_SET = 0x0000;
 
         /**
          * Placeholder for the theoretical strongest biometric security tier.
          * @hide
          */
-        int BIOMETRIC_MAX_STRENGTH = 0x001;
+        int BIOMETRIC_MAX_STRENGTH = 0x0001;
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
          * requirements for <strong>Strong</strong>, as defined by the Android CDD.
          */
-        int BIOMETRIC_STRONG = 0x00F;
+        int BIOMETRIC_STRONG = 0x000F;
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -111,7 +111,7 @@
          * <p>Note that this is a superset of {@link #BIOMETRIC_STRONG} and is defined such that
          * <code>BIOMETRIC_STRONG | BIOMETRIC_WEAK == BIOMETRIC_WEAK</code>.
          */
-        int BIOMETRIC_WEAK = 0x0FF;
+        int BIOMETRIC_WEAK = 0x00FF;
 
         /**
          * Any biometric (e.g. fingerprint, iris, or face) on the device that meets or exceeds the
@@ -121,7 +121,7 @@
          * @hide
          */
         @SystemApi
-        int BIOMETRIC_CONVENIENCE = 0xFFF;
+        int BIOMETRIC_CONVENIENCE = 0x0FFF;
 
         /**
          * Placeholder for the theoretical weakest biometric security tier.
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index c3ebe43..6f90db4 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -240,6 +240,11 @@
          *
          * <p>This value is looked up the first time, and cached subsequently.</p>
          *
+         * <p>This function may be called without cacheTag() if this is not a vendor key.
+         * If this is a vendor key, cacheTag() must be called first before getTag() can
+         * be called. Otherwise, mVendorId could be default (Long.MAX_VALUE) and vendor
+         * tag lookup could fail.</p>
+         *
          * @return The tag numeric value corresponding to the string
          */
         @UnsupportedAppUsage
@@ -252,6 +257,27 @@
         }
 
         /**
+         * Whether this key's tag is cached.
+         *
+         * @hide
+         */
+        @UnsupportedAppUsage
+        public final boolean hasTag() {
+            return mHasTag;
+        }
+
+        /**
+         * Cache this key's tag.
+         *
+         * @hide
+         */
+        @UnsupportedAppUsage
+        public final void cacheTag(int tag) {
+            mHasTag = true;
+            mTag = tag;
+        }
+
+        /**
          * Get the raw class backing the type {@code T} for this key.
          *
          * <p>The distinction is only important if {@code T} is a generic, e.g.
@@ -523,7 +549,13 @@
     }
 
     private <T> T getBase(Key<T> key) {
-        int tag = nativeGetTagFromKeyLocal(key.getName());
+        int tag;
+        if (key.hasTag()) {
+            tag = key.getTag();
+        } else {
+            tag = nativeGetTagFromKeyLocal(key.getName());
+            key.cacheTag(tag);
+        }
         byte[] values = readValues(tag);
         if (values == null) {
             // If the key returns null, use the fallback key if exists.
@@ -1451,7 +1483,13 @@
     }
 
     private <T> void setBase(Key<T> key, T value) {
-        int tag = nativeGetTagFromKeyLocal(key.getName());
+        int tag;
+        if (key.hasTag()) {
+            tag = key.getTag();
+        } else {
+            tag = nativeGetTagFromKeyLocal(key.getName());
+            key.cacheTag(tag);
+        }
         if (value == null) {
             // Erase the entry
             writeValues(tag, /*src*/null);
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 1c4ef382..3d44944 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2590,4 +2590,12 @@
      * @hide
      */
     public static native long getIonMappedSizeKb();
+
+    /**
+     * Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
+     * Note: caller needs config_gz read sepolicy permission
+     *
+     * @hide
+     */
+    public static native boolean isVmapStack();
 }
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index 2fd51a1..eca8541 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -20,7 +20,6 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Service;
 import android.content.Intent;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -88,7 +87,7 @@
      * {@link Control.StatelessBuilder}).
      * @param controls
      */
-    public void onLoad(@NonNull List<Control> controls) {
+    public final void onLoad(@NonNull List<Control> controls) {
         Preconditions.checkNotNull(controls);
         List<Control> list = new ArrayList<>();
         for (Control control: controls) {
@@ -114,7 +113,7 @@
      * their state.
      * @param statefulControls
      */
-    public void onRefreshState(@NonNull List<Control> statefulControls) {
+    public final void onRefreshState(@NonNull List<Control> statefulControls) {
         Preconditions.checkNotNull(statefulControls);
         try {
             mCallback.onRefreshState(mToken, statefulControls);
@@ -128,7 +127,7 @@
      * @param controlId
      * @param response
      */
-    public void onControlActionResponse(
+    public final void onControlActionResponse(
             @NonNull String controlId, @ControlAction.ResponseResult int response) {
         Preconditions.checkNotNull(controlId);
         if (!ControlAction.isValidResponse(response)) {
@@ -172,7 +171,7 @@
 
             public void onAction(String id, ControlAction action) {
                 ActionMessage msg = new ActionMessage(id, action);
-                mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, msg).sendToTarget();
+                mHandler.obtainMessage(RequestHandler.MSG_ON_ACTION, msg).sendToTarget();
             }
         };
     }
diff --git a/core/java/android/service/controls/templates/ThermostatTemplate.aidl b/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
similarity index 94%
rename from core/java/android/service/controls/templates/ThermostatTemplate.aidl
rename to core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
index 1fefda4..7994d26 100644
--- a/core/java/android/service/controls/templates/ThermostatTemplate.aidl
+++ b/core/java/android/service/controls/templates/TemperatureControlTemplate.aidl
@@ -16,4 +16,4 @@
 
 package android.service.controls.templates;
 
-parcelable ThermostatTemplate;
\ No newline at end of file
+parcelable TemperatureControlTemplate;
\ No newline at end of file
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 08e4eeb..5f74b2a 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -82,9 +82,6 @@
     // Input event dispatching is paused.
     public boolean paused;
 
-    // Window layer.
-    public int layer;
-
     // Id of process and user that owns the window.
     public int ownerPid;
     public int ownerUid;
@@ -126,7 +123,6 @@
     @Override
     public String toString() {
         return new StringBuilder(name != null ? name : "")
-                .append(", layer=").append(layer)
                 .append(", frame=[").append(frameLeft).append(",").append(frameTop).append(",")
                         .append(frameRight).append(",").append(frameBottom).append("]")
                 .append(", touchableRegion=").append(touchableRegion)
diff --git a/core/java/android/view/autofill/AutofillValue.java b/core/java/android/view/autofill/AutofillValue.java
index 64c8777..cfd624a 100644
--- a/core/java/android/view/autofill/AutofillValue.java
+++ b/core/java/android/view/autofill/AutofillValue.java
@@ -68,7 +68,7 @@
     }
 
     /**
-     * Checks is this is a text value.
+     * Checks if this is a text value.
      *
      * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.</p>
      */
@@ -89,7 +89,7 @@
     }
 
     /**
-     * Checks is this is a toggle value.
+     * Checks if this is a toggle value.
      *
      * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.</p>
      */
@@ -110,7 +110,7 @@
     }
 
     /**
-     * Checks is this is a list value.
+     * Checks if this is a list value.
      *
      * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.</p>
      */
@@ -131,7 +131,7 @@
     }
 
     /**
-     * Checks is this is a date value.
+     * Checks if this is a date value.
      *
      * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.</p>
      */
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a86b566..06e96d5 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -98,10 +98,10 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageView;
+import android.widget.Space;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -1546,6 +1546,21 @@
         return -1;
     }
 
+    @Override
+    protected boolean shouldAddFooterView() {
+        // To accommodate for window insets
+        return true;
+    }
+
+    @Override
+    protected void applyFooterView(int height) {
+        int count = mChooserMultiProfilePagerAdapter.getItemCount();
+
+        for (int i = 0; i < count; i++) {
+            mChooserMultiProfilePagerAdapter.getAdapterForIndex(i).setFooterHeight(height);
+        }
+    }
+
     void queryTargetServices(ChooserListAdapter adapter) {
         mQueriedTargetServicesTimeMs = System.currentTimeMillis();
 
@@ -2413,12 +2428,17 @@
     }
 
     /**
-     * Intentionally override the {@link ResolverActivity} implementation as we only need that
-     * implementation for the intent resolver case.
+     * Add a footer to the list, to support scrolling behavior below the navbar.
      */
-    @Override
-    protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
-        return insets.consumeSystemWindowInsets();
+    final class FooterViewHolder extends RecyclerView.ViewHolder {
+        FooterViewHolder(View itemView) {
+            super(itemView);
+        }
+
+        public void setHeight(int height) {
+            itemView.setLayoutParams(
+                    new RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, height));
+        }
     }
 
     /**
@@ -2451,11 +2471,14 @@
 
         private boolean mLayoutRequested = false;
 
+        private FooterViewHolder mFooterViewHolder;
+
         private static final int VIEW_TYPE_DIRECT_SHARE = 0;
         private static final int VIEW_TYPE_NORMAL = 1;
         private static final int VIEW_TYPE_PROFILE = 2;
         private static final int VIEW_TYPE_AZ_LABEL = 3;
         private static final int VIEW_TYPE_CALLER_AND_RANK = 4;
+        private static final int VIEW_TYPE_FOOTER = 5;
 
         private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
         private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
@@ -2467,6 +2490,9 @@
             mChooserListAdapter = wrappedAdapter;
             mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
 
+            mFooterViewHolder = new FooterViewHolder(
+                    new Space(ChooserActivity.this.getApplicationContext()));
+
             mShowAzLabelIfPoss = getNumSheetExpansions() < NUM_EXPANSIONS_TO_HIDE_AZ_LABEL;
 
             wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -2484,6 +2510,10 @@
             });
         }
 
+        public void setFooterHeight(int height) {
+            mFooterViewHolder.setHeight(height);
+        }
+
         /**
          * Calculate the chooser target width to maximize space per item
          *
@@ -2534,6 +2564,10 @@
             return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
         }
 
+        public int getFooterRowCount() {
+            return 1;
+        }
+
         public int getCallerAndRankedTargetRowCount() {
             return (int) Math.ceil(
                     ((float) mChooserListAdapter.getCallerTargetCount()
@@ -2563,6 +2597,7 @@
                             + getCallerAndRankedTargetRowCount()
                             + getAzLabelRowCount()
                             + mChooserListAdapter.getAlphaTargetCount()
+                            + getFooterRowCount()
             );
         }
 
@@ -2578,6 +2613,8 @@
                 case VIEW_TYPE_DIRECT_SHARE:
                 case VIEW_TYPE_CALLER_AND_RANK:
                     return createItemGroupViewHolder(viewType, parent);
+                case VIEW_TYPE_FOOTER:
+                    return mFooterViewHolder;
                 default:
                     // Since we catch all possible viewTypes above, no chance this is being called.
                     return null;
@@ -2615,6 +2652,8 @@
             countSum += (count = getAzLabelRowCount());
             if (count > 0 && position < countSum) return VIEW_TYPE_AZ_LABEL;
 
+            if (position == getItemCount() - 1) return VIEW_TYPE_FOOTER;
+
             return VIEW_TYPE_NORMAL;
         }
 
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 8dc3a07..8d3c572 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -353,7 +353,11 @@
                     finish();
                 }
             });
-            if (isVoiceInteraction()) {
+
+            boolean hasTouchScreen = getPackageManager()
+                    .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+
+            if (isVoiceInteraction() || !hasTouchScreen) {
                 rdl.setCollapsed(false);
             }
 
@@ -472,34 +476,52 @@
         finish();
     }
 
+    /**
+     * Numerous layouts are supported, each with optional ViewGroups.
+     * Make sure the inset gets added to the correct View, using
+     * a footer for Lists so it can properly scroll under the navbar.
+     */
+    protected boolean shouldAddFooterView() {
+        if (useLayoutWithDefault()) return true;
+
+        View buttonBar = findViewById(R.id.button_bar);
+        if (buttonBar == null || buttonBar.getVisibility() == View.GONE) return true;
+
+        return false;
+    }
+
+    protected void applyFooterView(int height) {
+        if (mFooterSpacer == null) {
+            mFooterSpacer = new Space(getApplicationContext());
+        } else {
+            ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+                .getCurrentAdapterView().removeFooterView(mFooterSpacer);
+        }
+        mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
+                                                                   mSystemWindowInsets.bottom));
+        ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
+            .getCurrentAdapterView().addFooterView(mFooterSpacer);
+    }
+
     protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
         mSystemWindowInsets = insets.getSystemWindowInsets();
 
         mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
                 mSystemWindowInsets.right, 0);
 
+        resetButtonBar();
+
         // Need extra padding so the list can fully scroll up
-        if (useLayoutWithDefault()) {
-            if (mFooterSpacer == null) {
-                mFooterSpacer = new Space(getApplicationContext());
-            } else {
-                ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
-                        .getCurrentAdapterView().removeFooterView(mFooterSpacer);
-            }
-            mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
-                                                                       mSystemWindowInsets.bottom));
-            ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
-                    .getCurrentAdapterView().addFooterView(mFooterSpacer);
-        } else {
-            View emptyView = findViewById(R.id.empty);
-            if (emptyView != null) {
-                emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
-                                     + getResources().getDimensionPixelSize(
-                                             R.dimen.chooser_edge_margin_normal) * 2);
-            }
+        if (shouldAddFooterView()) {
+            applyFooterView(mSystemWindowInsets.bottom);
         }
 
-        resetButtonBar();
+        View emptyView = findViewById(R.id.empty);
+        if (emptyView != null) {
+            emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+                                 + getResources().getDimensionPixelSize(
+                                         R.dimen.chooser_edge_margin_normal) * 2);
+        }
 
         return insets.consumeSystemWindowInsets();
     }
@@ -1283,10 +1305,11 @@
 
         // In case this method is called again (due to activity recreation), avoid adding a new
         // header if one is already present.
-        if (useHeader && listView != null && listView.getHeaderViewsCount() == 0) {
+        if (useHeader && listView.getHeaderViewsCount() == 0) {
             listView.setHeaderDividersEnabled(true);
             listView.addHeaderView(LayoutInflater.from(this).inflate(
-                    R.layout.resolver_different_item_header, listView, false));
+                    R.layout.resolver_different_item_header, listView, false),
+                    null, false);
         }
     }
 
@@ -1349,6 +1372,8 @@
         if (useLayoutWithDefault() && filteredPosition != ListView.INVALID_POSITION) {
             setAlwaysButtonEnabled(true, filteredPosition, false);
             mOnceButton.setEnabled(true);
+            // Focus the button if we already have the default option
+            mOnceButton.requestFocus();
             return;
         }
 
@@ -1481,6 +1506,7 @@
                 mOnceButton.setEnabled(hasValidSelection);
                 if (hasValidSelection) {
                     currentAdapterView.smoothScrollToPosition(checkedPos);
+                    mOnceButton.requestFocus();
                 }
                 mLastSelected = checkedPos;
             } else {
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 4a21d37..8d281b7 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -184,9 +184,8 @@
                             Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
         }
 
-        fetchUsapPoolPolicyProps();
-
         mUsapPoolSupported = true;
+        fetchUsapPoolPolicyProps();
     }
 
     void setForkChild() {
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index 362bc92..580c2fa 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -107,9 +107,12 @@
      * Amount of RAM that is in use by the kernel for actual allocations.
      */
     public long getKernelUsedSizeKb() {
-        return mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
-                + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES]
-                + mInfos[Debug.MEMINFO_KERNEL_STACK];
+        long size = mInfos[Debug.MEMINFO_SHMEM] + mInfos[Debug.MEMINFO_SLAB_UNRECLAIMABLE]
+                + mInfos[Debug.MEMINFO_VM_ALLOC_USED] + mInfos[Debug.MEMINFO_PAGE_TABLES];
+        if (!Debug.isVmapStack()) {
+            size += mInfos[Debug.MEMINFO_KERNEL_STACK];
+        }
+        return size;
     }
 
     public long getSwapTotalSizeKb() {
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 1bb2ba2..e0c3823 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -187,7 +187,7 @@
 
     public void setCollapsed(boolean collapsed) {
         if (!isLaidOut()) {
-            mOpenOnLayout = collapsed;
+            mOpenOnLayout = !collapsed;
         } else {
             smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0);
         }
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index 2265268..79f62cb 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -59,7 +59,6 @@
     jfieldID hasFocus;
     jfieldID hasWallpaper;
     jfieldID paused;
-    jfieldID layer;
     jfieldID ownerPid;
     jfieldID ownerUid;
     jfieldID inputFeatures;
@@ -152,8 +151,6 @@
             gInputWindowHandleClassInfo.hasWallpaper);
     mInfo.paused = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.paused);
-    mInfo.layer = env->GetIntField(obj,
-            gInputWindowHandleClassInfo.layer);
     mInfo.ownerPid = env->GetIntField(obj,
             gInputWindowHandleClassInfo.ownerPid);
     mInfo.ownerUid = env->GetIntField(obj,
@@ -332,9 +329,6 @@
     GET_FIELD_ID(gInputWindowHandleClassInfo.paused, clazz,
             "paused", "Z");
 
-    GET_FIELD_ID(gInputWindowHandleClassInfo.layer, clazz,
-            "layer", "I");
-
     GET_FIELD_ID(gInputWindowHandleClassInfo.ownerPid, clazz,
             "ownerPid", "I");
 
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 6e0d5d8..4314eb6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -50,6 +50,7 @@
 #include <memunreachable/memunreachable.h>
 #include <android-base/strings.h>
 #include "android_os_Debug.h"
+#include <vintf/VintfObject.h>
 
 namespace android
 {
@@ -835,6 +836,23 @@
     return ionPss;
 }
 
+static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
+{
+    static enum {
+        CONFIG_UNKNOWN,
+        CONFIG_SET,
+        CONFIG_UNSET,
+    } cfg_state = CONFIG_UNKNOWN;
+
+    if (cfg_state == CONFIG_UNKNOWN) {
+        const std::map<std::string, std::string> configs =
+            vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs();
+        std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
+        cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
+    }
+    return cfg_state == CONFIG_SET;
+}
+
 /*
  * JNI registration.
  */
@@ -884,6 +902,8 @@
             (void*)android_os_Debug_getIonPoolsSizeKb },
     { "getIonMappedSizeKb", "()J",
             (void*)android_os_Debug_getIonMappedSizeKb },
+    { "isVmapStack", "()Z",
+            (void*)android_os_Debug_isVmapStack },
 };
 
 int register_android_os_Debug(JNIEnv *env)
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e874ac7..a00296c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3209,11 +3209,6 @@
   <java-symbol type="id" name="accessibility_button_target_label" />
   <java-symbol type="string" name="accessibility_magnification_chooser_text" />
 
-  <java-symbol type="string" name="accessibility_gesture_prompt_text" />
-  <java-symbol type="string" name="accessibility_gesture_3finger_prompt_text" />
-  <java-symbol type="string" name="accessibility_gesture_instructional_text" />
-  <java-symbol type="string" name="accessibility_gesture_3finger_instructional_text" />
-
   <java-symbol type="drawable" name="ic_accessibility_magnification" />
 
   <!-- com.android.internal.widget.RecyclerView -->
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 8622b7e..c086421 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -54,6 +54,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.res.Configuration;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -977,6 +978,7 @@
                         serviceTargets,
                         TARGET_TYPE_CHOOSER_TARGET)
         );
+
         // Thread.sleep shouldn't be a thing in an integration test but it's
         // necessary here because of the way the code is structured
         // TODO: restructure the tests b/129870719
@@ -1075,7 +1077,29 @@
 
     // This test is too long and too slow and should not be taken as an example for future tests.
     @Test
-    public void testDirectTargetLoggingWithAppTargetNotRanked() throws InterruptedException {
+    public void testDirectTargetLoggingWithAppTargetNotRankedPortrait()
+            throws InterruptedException {
+        testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_PORTRAIT, 4);
+    }
+
+    @Test
+    public void testDirectTargetLoggingWithAppTargetNotRankedLandscape()
+            throws InterruptedException {
+        testDirectTargetLoggingWithAppTargetNotRanked(Configuration.ORIENTATION_LANDSCAPE, 8);
+    }
+
+    private void testDirectTargetLoggingWithAppTargetNotRanked(
+            int orientation, int appTargetsExpected
+    ) throws InterruptedException {
+        Configuration configuration =
+                new Configuration(InstrumentationRegistry.getInstrumentation().getContext()
+                        .getResources().getConfiguration());
+        configuration.orientation = orientation;
+
+        sOverrides.resources = Mockito.spy(
+                InstrumentationRegistry.getInstrumentation().getContext().getResources());
+        when(sOverrides.resources.getConfiguration()).thenReturn(configuration);
+
         Intent sendIntent = createSendTextIntent();
         // We need app targets for direct targets to get displayed
         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
@@ -1111,8 +1135,10 @@
         // TODO: restructure the tests b/129870719
         Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
 
-        assertThat("Chooser should have 20 targets (4 apps, 1 direct, 15 A-Z)",
-                activity.getAdapter().getCount(), is(20));
+        assertThat(
+                String.format("Chooser should have %d targets (%d apps, 1 direct, 15 A-Z)",
+                        appTargetsExpected + 16, appTargetsExpected),
+                activity.getAdapter().getCount(), is(appTargetsExpected + 16));
         assertThat("Chooser should have exactly one selectable direct target",
                 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
         assertThat("The resolver info must match the resolver info used to create the target",
diff --git a/media/Android.bp b/media/Android.bp
index a136517..499d0da 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -1,110 +1,3 @@
-java_library {
-    name: "updatable-media",
-
-    srcs: [
-        ":updatable-media-srcs",
-    ],
-
-    aidl: {
-        export_include_dirs: [
-            "apex/java",
-        ],
-
-        // It would be great if we don't need to add include_dirs for public
-        // parcelable classes. Find a better way.
-        include_dirs: [
-            // To refer:
-            // android.os.Bundle
-            // android.os.ResultReceiver
-            "frameworks/base/core/java",
-        ],
-    },
-
-    permitted_packages: [
-        "android.media",
-    ],
-
-    installable: true,
-
-    // TODO: build against stable API surface. Use core_platform for now to avoid
-    // link-check failure with exoplayer building against "current".
-    sdk_version: "core_platform",
-    libs: [
-        // The order matters. android_system_* library should come later.
-        "framework_media_annotation",
-        "android_system_stubs_current",
-    ],
-
-    static_libs: [
-        "exoplayer2-core"
-    ],
-    jarjar_rules: "jarjar_rules.txt",
-
-    plugins: ["java_api_finder"],
-}
-
-filegroup {
-    name: "updatable-media-srcs",
-    srcs: [
-        ":mediaparser-srcs",
-        ":mediasession2-srcs",
-    ],
-}
-
-filegroup {
-    name: "mediasession2-srcs",
-    srcs: [
-        "apex/java/android/media/Controller2Link.java",
-        "apex/java/android/media/IMediaController2.aidl",
-        "apex/java/android/media/IMediaSession2.aidl",
-        "apex/java/android/media/IMediaSession2Service.aidl",
-        "apex/java/android/media/MediaConstants.java",
-        "apex/java/android/media/MediaController2.java",
-        "apex/java/android/media/MediaSession2.java",
-        "apex/java/android/media/MediaSession2Service.java",
-        "apex/java/android/media/Session2Command.java",
-        "apex/java/android/media/Session2CommandGroup.java",
-        "apex/java/android/media/Session2Link.java",
-        "apex/java/android/media/Session2Token.java",
-    ],
-    path: "apex/java",
-}
-
-filegroup {
-    name: "mediaparser-srcs",
-    srcs: [
-        "apex/java/android/media/MediaParser.java"
-    ],
-    path: "apex/java"
-}
-
-droidstubs {
-    name: "updatable-media-stubs",
-    srcs: [
-        ":updatable-media-srcs",
-        ":framework-media-annotation-srcs",
-    ],
-    defaults: [ "framework-module-stubs-defaults-systemapi" ],
-    aidl: {
-        // TODO(b/135922046) remove this
-        include_dirs: ["frameworks/base/core/java"],
-    },
-    sdk_version: "system_current",
-}
-
-java_library {
-    name: "updatable_media_stubs",
-    srcs: [":updatable-media-stubs"],
-    sdk_version: "system_current",
-}
-
-java_library {
-    name: "framework_media_annotation",
-    srcs: [":framework-media-annotation-srcs"],
-    installable: false,
-    sdk_version: "core_current",
-}
-
 aidl_interface {
     name: "audio_common-aidl",
     local_include_dir: "java",
diff --git a/media/apex/java/android/media/CloseGuard.java b/media/apex/java/android/media/CloseGuard.java
deleted file mode 100644
index 2014673..0000000
--- a/media/apex/java/android/media/CloseGuard.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.util.Log;
-
-/**
- * Note: This file is copied from dalvik.system package with the following modifications:
- *       - Remove @CorePlatformApi, @IntraCoreApi and @UnsupportedAppUsage annotations.
- *       - Replace System.logW() with android.util.Log.w().
- *       This file should be used only within media mainline module.
- * TODO: Remove this file and use dalvik.system.CloseGuard once
- *       @CorePlatformApi becomes stable or we have a replacement in SDK API.
- *       b/120419300
- *
- * CloseGuard is a mechanism for flagging implicit finalizer cleanup of
- * resources that should have been cleaned up by explicit close
- * methods (aka "explicit termination methods" in Effective Java).
- * <p>
- * A simple example: <pre>   {@code
- *   class Foo {
- *
- *       {@literal @}ReachabilitySensitive
- *       private final CloseGuard guard = CloseGuard.get();
- *
- *       ...
- *
- *       public Foo() {
- *           ...;
- *           guard.open("cleanup");
- *       }
- *
- *       public void cleanup() {
- *          guard.close();
- *          ...;
- *       }
- *
- *       protected void finalize() throws Throwable {
- *           try {
- *               // Note that guard could be null if the constructor threw.
- *               if (guard != null) {
- *                   guard.warnIfOpen();
- *               }
- *               cleanup();
- *           } finally {
- *               super.finalize();
- *           }
- *       }
- *   }
- * }</pre>
- *
- * In usage where the resource to be explicitly cleaned up is
- * allocated after object construction, CloseGuard protection can
- * be deferred. For example: <pre>   {@code
- *   class Bar {
- *
- *       {@literal @}ReachabilitySensitive
- *       private final CloseGuard guard = CloseGuard.get();
- *
- *       ...
- *
- *       public Bar() {
- *           ...;
- *       }
- *
- *       public void connect() {
- *          ...;
- *          guard.open("cleanup");
- *       }
- *
- *       public void cleanup() {
- *          guard.close();
- *          ...;
- *       }
- *
- *       protected void finalize() throws Throwable {
- *           try {
- *               // Note that guard could be null if the constructor threw.
- *               if (guard != null) {
- *                   guard.warnIfOpen();
- *               }
- *               cleanup();
- *           } finally {
- *               super.finalize();
- *           }
- *       }
- *   }
- * }</pre>
- *
- * When used in a constructor, calls to {@code open} should occur at
- * the end of the constructor since an exception that would cause
- * abrupt termination of the constructor will mean that the user will
- * not have a reference to the object to cleanup explicitly. When used
- * in a method, the call to {@code open} should occur just after
- * resource acquisition.
- *
- * The @ReachabilitySensitive annotation ensures that finalize() cannot be
- * called during the explicit call to cleanup(), prior to the guard.close call.
- * There is an extremely small chance that, for code that neglects to call
- * cleanup(), finalize() and thus cleanup() will be called while a method on
- * the object is still active, but the "this" reference is no longer required.
- * If missing cleanup() calls are expected, additional @ReachabilitySensitive
- * annotations or reachabilityFence() calls may be required.
- *
- * @hide
- */
-final class CloseGuard {
-
-    /**
-     * True if collection of call-site information (the expensive operation
-     * here)  and tracking via a Tracker (see below) are enabled.
-     * Enabled by default so we can diagnose issues early in VM startup.
-     * Note, however, that Android disables this early in its startup,
-     * but enables it with DropBoxing for system apps on debug builds.
-     */
-    private static volatile boolean stackAndTrackingEnabled = true;
-
-    /**
-     * Hook for customizing how CloseGuard issues are reported.
-     * Bypassed if stackAndTrackingEnabled was false when open was called.
-     */
-    private static volatile Reporter reporter = new DefaultReporter();
-
-    /**
-     * Hook for customizing how CloseGuard issues are tracked.
-     */
-    private static volatile Tracker currentTracker = null; // Disabled by default.
-
-    /**
-     * Returns a CloseGuard instance. {@code #open(String)} can be used to set
-     * up the instance to warn on failure to close.
-     */
-    public static CloseGuard get() {
-        return new CloseGuard();
-    }
-
-    /**
-     * Enables/disables stack capture and tracking. A call stack is captured
-     * during open(), and open/close events are reported to the Tracker, only
-     * if enabled is true. If a stack trace was captured, the {@link
-     * #getReporter() reporter} is informed of unclosed resources; otherwise a
-     * one-line warning is logged.
-     */
-    public static void setEnabled(boolean enabled) {
-        CloseGuard.stackAndTrackingEnabled = enabled;
-    }
-
-    /**
-     * True if CloseGuard stack capture and tracking are enabled.
-     */
-    public static boolean isEnabled() {
-        return stackAndTrackingEnabled;
-    }
-
-    /**
-     * Used to replace default Reporter used to warn of CloseGuard
-     * violations when stack tracking is enabled. Must be non-null.
-     */
-    public static void setReporter(Reporter rep) {
-        if (rep == null) {
-            throw new NullPointerException("reporter == null");
-        }
-        CloseGuard.reporter = rep;
-    }
-
-    /**
-     * Returns non-null CloseGuard.Reporter.
-     */
-    public static Reporter getReporter() {
-        return reporter;
-    }
-
-    /**
-     * Sets the {@link Tracker} that is notified when resources are allocated and released.
-     * The Tracker is invoked only if CloseGuard {@link #isEnabled()} held when {@link #open()}
-     * was called. A null argument disables tracking.
-     *
-     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
-     * MUST NOT be used for any other purposes.
-     */
-    public static void setTracker(Tracker tracker) {
-        currentTracker = tracker;
-    }
-
-    /**
-     * Returns {@link #setTracker(Tracker) last Tracker that was set}, or null to indicate
-     * there is none.
-     *
-     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
-     * MUST NOT be used for any other purposes.
-     */
-    public static Tracker getTracker() {
-        return currentTracker;
-    }
-
-    private CloseGuard() {}
-
-    /**
-     * {@code open} initializes the instance with a warning that the caller
-     * should have explicitly called the {@code closer} method instead of
-     * relying on finalization.
-     *
-     * @param closer non-null name of explicit termination method. Printed by warnIfOpen.
-     * @throws NullPointerException if closer is null.
-     */
-    public void open(String closer) {
-        // always perform the check for valid API usage...
-        if (closer == null) {
-            throw new NullPointerException("closer == null");
-        }
-        // ...but avoid allocating an allocation stack if "disabled"
-        if (!stackAndTrackingEnabled) {
-            closerNameOrAllocationInfo = closer;
-            return;
-        }
-        String message = "Explicit termination method '" + closer + "' not called";
-        Throwable stack = new Throwable(message);
-        closerNameOrAllocationInfo = stack;
-        Tracker tracker = currentTracker;
-        if (tracker != null) {
-            tracker.open(stack);
-        }
-    }
-
-    // We keep either an allocation stack containing the closer String or, when
-    // in disabled state, just the closer String.
-    // We keep them in a single field only to minimize overhead.
-    private Object /* String or Throwable */ closerNameOrAllocationInfo;
-
-    /**
-     * Marks this CloseGuard instance as closed to avoid warnings on
-     * finalization.
-     */
-    public void close() {
-        Tracker tracker = currentTracker;
-        if (tracker != null && closerNameOrAllocationInfo instanceof Throwable) {
-            // Invoke tracker on close only if we invoked it on open. Tracker may have changed.
-            tracker.close((Throwable) closerNameOrAllocationInfo);
-        }
-        closerNameOrAllocationInfo = null;
-    }
-
-    /**
-     * Logs a warning if the caller did not properly cleanup by calling an
-     * explicit close method before finalization. If CloseGuard was enabled
-     * when the CloseGuard was created, passes the stacktrace associated with
-     * the allocation to the current reporter. If it was not enabled, it just
-     * directly logs a brief message.
-     */
-    public void warnIfOpen() {
-        if (closerNameOrAllocationInfo != null) {
-            if (closerNameOrAllocationInfo instanceof String) {
-                Log.w("CloseGuard", "A resource failed to call "
-                        + (String) closerNameOrAllocationInfo + ". ");
-            } else {
-                String message =
-                        "A resource was acquired at attached stack trace but never released. ";
-                message += "See java.io.Closeable for information on avoiding resource leaks.";
-                Throwable stack = (Throwable) closerNameOrAllocationInfo;
-                reporter.report(message, stack);
-            }
-        }
-    }
-
-    /**
-     * Interface to allow customization of tracking behaviour.
-     *
-     * <p>This is only intended for use by {@code dalvik.system.CloseGuardSupport} class and so
-     * MUST NOT be used for any other purposes.
-     */
-    public interface Tracker {
-        void open(Throwable allocationSite);
-        void close(Throwable allocationSite);
-    }
-
-    /**
-     * Interface to allow customization of reporting behavior.
-     * @hide
-     */
-    public interface Reporter {
-        void report(String message, Throwable allocationSite);
-    }
-
-    /**
-     * Default Reporter which reports CloseGuard violations to the log.
-     */
-    private static final class DefaultReporter implements Reporter {
-        private DefaultReporter() {}
-
-        @Override public void report (String message, Throwable allocationSite) {
-            Log.w("CloseGuard", message, allocationSite);
-        }
-    }
-}
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 5f32c0f..f3613d3 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.media.audiofx.AudioEffect;
@@ -224,15 +225,16 @@
     public String getClientPackageName() { return mClientPackageName; }
 
     /**
-     * @pending for SystemApi
      * Returns the user id of the application performing the recording.
      * <p>This information is only available if the caller has the
      * {@link android.Manifest.permission.MODIFY_AUDIO_ROUTING}
      * permission.
      * <br>The result is -1 without the permission.
      * @return the user id
+     *
+     * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public int getClientUid() { return mClientUid; }
 
     /**
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 176bb37..f780d40 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -362,7 +362,8 @@
    </tr>
    <tr>
     <td>FLAC</td>
-    <td>mandatory metadata block (called the STREAMINFO block),<br>
+    <td>"fLaC", the FLAC stream marker in ASCII,<br>
+        followed by the STREAMINFO block (the mandatory metadata block),<br>
         optionally followed by any number of other metadata blocks</td>
     <td class=NA>Not Used</td>
     <td class=NA>Not Used</td>
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 0be49d8..9100032 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -547,8 +547,6 @@
      * {@link SessionCallback#onSessionCreationFailed}.
      * <p>
      * Pass {@code null} to sessionInfo for the failure case.
-     *
-     * TODO: What should router do when the session is created by manager?
      */
     void createControllerOnHandler(@Nullable RouteSessionInfo sessionInfo, int requestId) {
         SessionCreationRequest matchingRequest = null;
@@ -559,40 +557,44 @@
             }
         }
 
-        if (matchingRequest == null) {
-            Log.w(TAG, "Ignoring session creation result for unknown request."
-                    + " requestId=" + requestId + ", sessionInfo=" + sessionInfo);
-            return;
+        if (matchingRequest != null) {
+            mSessionCreationRequests.remove(matchingRequest);
+
+            MediaRoute2Info requestedRoute = matchingRequest.mRoute;
+            String requestedControlCategory = matchingRequest.mControlCategory;
+
+            if (sessionInfo == null) {
+                // TODO: We may need to distinguish between failure and rejection.
+                //       One way can be introducing 'reason'.
+                notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+                return;
+            } else if (!TextUtils.equals(requestedControlCategory,
+                    sessionInfo.getControlCategory())) {
+                Log.w(TAG, "The session has different control category from what we requested. "
+                        + "(requested=" + requestedControlCategory
+                        + ", actual=" + sessionInfo.getControlCategory()
+                        + ")");
+                notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+                return;
+            } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
+                Log.w(TAG, "The session does not contain the requested route. "
+                        + "(requestedRouteId=" + requestedRoute.getId()
+                        + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
+                        + ")");
+                notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+                return;
+            } else if (!TextUtils.equals(requestedRoute.getProviderId(),
+                    sessionInfo.getProviderId())) {
+                Log.w(TAG, "The session's provider ID does not match the requested route's. "
+                        + "(requested route's providerId=" + requestedRoute.getProviderId()
+                        + ", actual providerId=" + sessionInfo.getProviderId()
+                        + ")");
+                notifySessionCreationFailed(requestedRoute, requestedControlCategory);
+                return;
+            }
         }
 
-        mSessionCreationRequests.remove(matchingRequest);
-
-        MediaRoute2Info requestedRoute = matchingRequest.mRoute;
-        String requestedControlCategory = matchingRequest.mControlCategory;
-
-        if (sessionInfo == null) {
-            // TODO: We may need to distinguish between failure and rejection.
-            //       One way can be introducing 'reason'.
-            notifySessionCreationFailed(requestedRoute, requestedControlCategory);
-        } else if (!TextUtils.equals(requestedControlCategory, sessionInfo.getControlCategory())) {
-            Log.w(TAG, "The session has different control category from what we requested. "
-                    + "(requested=" + requestedControlCategory
-                    + ", actual=" + sessionInfo.getControlCategory()
-                    + ")");
-            notifySessionCreationFailed(requestedRoute, requestedControlCategory);
-        } else if (!sessionInfo.getSelectedRoutes().contains(requestedRoute.getId())) {
-            Log.w(TAG, "The session does not contain the requested route. "
-                    + "(requestedRouteId=" + requestedRoute.getId()
-                    + ", actualRoutes=" + sessionInfo.getSelectedRoutes()
-                    + ")");
-            notifySessionCreationFailed(requestedRoute, requestedControlCategory);
-        } else if (!TextUtils.equals(requestedRoute.getProviderId(), sessionInfo.getProviderId())) {
-            Log.w(TAG, "The session's provider ID does not match the requested route's. "
-                    + "(requested route's providerId=" + requestedRoute.getProviderId()
-                    + ", actual providerId=" + sessionInfo.getProviderId()
-                    + ")");
-            notifySessionCreationFailed(requestedRoute, requestedControlCategory);
-        } else {
+        if (sessionInfo != null) {
             RouteSessionController controller = new RouteSessionController(sessionInfo);
             mSessionControllers.put(controller.getUniqueSessionId(), controller);
             notifySessionCreated(controller);
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index ef806e4..da52696 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -966,7 +966,7 @@
     { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
     { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
     { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
-    { "nativeCloseFilter", "()I", (void *)android_media_tv_Tuner_close_filter },
+    { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
 };
 
 static const JNINativeMethod gDescramblerMethods[] = {
@@ -975,7 +975,7 @@
     { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
             (void *)android_media_tv_Tuner_remove_pid },
     { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
-    { "nativeClose", "()V", (void *)android_media_tv_Tuner_close_descrambler },
+    { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
 };
 
 static const JNINativeMethod gDvrMethods[] = {
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 1d51c96..83c7c17 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -29,6 +29,7 @@
 import android.media.MediaRoute2Info;
 import android.media.MediaRouter2;
 import android.media.MediaRouter2.RouteCallback;
+import android.media.MediaRouter2.SessionCallback;
 import android.media.MediaRouter2Manager;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -101,8 +102,8 @@
     private String mPackageName;
 
     private final List<MediaRouter2Manager.Callback> mManagerCallbacks = new ArrayList<>();
-    private final List<RouteCallback> mRouteCallbacks =
-            new ArrayList<>();
+    private final List<RouteCallback> mRouteCallbacks = new ArrayList<>();
+    private final List<SessionCallback> mSessionCallbacks = new ArrayList<>();
 
     public static final List<String> CATEGORIES_ALL = new ArrayList();
     public static final List<String> CATEGORIES_SPECIAL = new ArrayList();
@@ -205,27 +206,26 @@
     }
 
     /**
-     * Tests if MR2.Callback.onRouteSelected is called when a route is selected from MR2Manager.
-     *
-     * TODO: Change this test so that this test check whether the route is added in a session.
-     *       Until then, temporailiy marking @Ignore
+     * Tests if MR2.SessionCallback.onSessionCreated is called
+     * when a route is selected from MR2Manager.
      */
     @Test
-    @Ignore
-    public void testRouterOnRouteSelected() throws Exception {
+    public void testRouterOnSessionCreated() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
 
         CountDownLatch latch = new CountDownLatch(1);
 
         addManagerCallback(new MediaRouter2Manager.Callback());
-//        addRouterCallback(new RouteDiscoveryCallback() {
-//            @Override
-//            public void onRouteSelected(MediaRoute2Info route, int reason, Bundle controlHints) {
-//                if (route != null && TextUtils.equals(route.getId(), ROUTE_ID1)) {
-//                    latch.countDown();
-//                }
-//            }
-//        });
+        //TODO: remove this when it's not necessary.
+        addRouterCallback(new MediaRouter2.RouteCallback());
+        addSessionCallback(new SessionCallback() {
+            @Override
+            public void onSessionCreated(MediaRouter2.RouteSessionController controller) {
+                if (createRouteMap(controller.getSelectedRoutes()).containsKey(ROUTE_ID1)) {
+                    latch.countDown();
+                }
+            }
+        });
 
         MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
         assertNotNull(routeToSelect);
@@ -446,6 +446,11 @@
         mRouter2.registerRouteCallback(mExecutor, routeCallback);
     }
 
+    private void addSessionCallback(SessionCallback sessionCallback) {
+        mSessionCallbacks.add(sessionCallback);
+        mRouter2.registerSessionCallback(mExecutor, sessionCallback);
+    }
+
     private void clearCallbacks() {
         for (MediaRouter2Manager.Callback callback : mManagerCallbacks) {
             mManager.unregisterCallback(callback);
@@ -456,5 +461,10 @@
             mRouter2.unregisterRouteCallback(routeCallback);
         }
         mRouteCallbacks.clear();
+
+        for (SessionCallback sessionCallback : mSessionCallbacks) {
+            mRouter2.unregisterSessionCallback(sessionCallback);
+        }
+        mSessionCallbacks.clear();
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 58655a2..b4b55f3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -203,13 +203,6 @@
         }
     }
 
-    public int getVolume() {
-        if (mService == null) {
-            return 0;
-        }
-        return mService.getVolume();
-    }
-
     public void setVolume(int volume) {
         if (mService == null) {
             return;
@@ -224,20 +217,6 @@
         return mService.getHiSyncId(device);
     }
 
-    public int getDeviceSide(BluetoothDevice device) {
-        if (mService == null) {
-            return BluetoothHearingAid.SIDE_LEFT;
-        }
-        return mService.getDeviceSide(device);
-    }
-
-    public int getDeviceMode(BluetoothDevice device) {
-        if (mService == null) {
-            return BluetoothHearingAid.MODE_MONAURAL;
-        }
-        return mService.getDeviceMode(device);
-    }
-
     public String toString() {
         return NAME;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 9261412..bbff117 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -42,6 +42,7 @@
 
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Manages the lifecycle of a TileService.
@@ -84,7 +85,8 @@
     private int mBindTryCount;
     private int mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
     private boolean mBound;
-    boolean mReceiverRegistered;
+    private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
+    private AtomicBoolean mUserReceiverRegistered = new AtomicBoolean(false);
     private boolean mUnbindImmediate;
     private TileChangeListener mChangeListener;
     // Return value from bindServiceAsUser, determines whether safe to call unbind.
@@ -274,7 +276,7 @@
 
     public void handleDestroy() {
         if (DEBUG) Log.d(TAG, "handleDestroy");
-        if (mReceiverRegistered) {
+        if (mPackageReceiverRegistered.get() || mUserReceiverRegistered.get()) {
             stopPackageListening();
         }
     }
@@ -310,17 +312,31 @@
         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
-        mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+        try {
+            mPackageReceiverRegistered.set(true);
+            mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+        } catch (Exception ex) {
+            mPackageReceiverRegistered.set(false);
+            Log.e(TAG, "Could not register package receiver", ex);
+        }
         filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
-        mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
-        mReceiverRegistered = true;
+        try {
+            mUserReceiverRegistered.set(true);
+            mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
+        } catch (Exception ex) {
+            mUserReceiverRegistered.set(false);
+            Log.e(TAG, "Could not register unlock receiver", ex);
+        }
     }
 
     private void stopPackageListening() {
         if (DEBUG) Log.d(TAG, "stopPackageListening");
-        mContext.unregisterReceiver(this);
-        mBroadcastDispatcher.unregisterReceiver(this);
-        mReceiverRegistered = false;
+        if (mUserReceiverRegistered.compareAndSet(true, false)) {
+            mBroadcastDispatcher.unregisterReceiver(this);
+        }
+        if (mPackageReceiverRegistered.compareAndSet(true, false)) {
+            mContext.unregisterReceiver(this);
+        }
     }
 
     public void setTileChangeListener(TileChangeListener changeListener) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 9a33c8c..f06c849 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -38,7 +38,6 @@
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.FlashlightTile;
 import com.android.systemui.qs.tiles.HotspotTile;
-import com.android.systemui.qs.tiles.IntentTile;
 import com.android.systemui.qs.tiles.LocationTile;
 import com.android.systemui.qs.tiles.NfcTile;
 import com.android.systemui.qs.tiles.NightDisplayTile;
@@ -182,8 +181,7 @@
                 return mUiModeNightTileProvider.get();
         }
 
-        // Intent tiles.
-        if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(mHost, tileSpec);
+        // Custom tiles
         if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(mHost, tileSpec);
 
         // Debug tiles.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
deleted file mode 100644
index a639a95..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.qs.tiles;
-
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-public class IntentTile extends QSTileImpl<State> {
-    public static final String PREFIX = "intent(";
-
-    private PendingIntent mOnClick;
-    private String mOnClickUri;
-    private PendingIntent mOnLongClick;
-    private String mOnLongClickUri;
-    private int mCurrentUserId;
-    private String mIntentPackage;
-
-    private Intent mLastIntent;
-
-    private IntentTile(QSHost host, String action) {
-        super(host);
-        mContext.registerReceiver(mReceiver, new IntentFilter(action));
-    }
-
-    @Override
-    protected void handleDestroy() {
-        super.handleDestroy();
-        mContext.unregisterReceiver(mReceiver);
-    }
-
-    public static IntentTile create(QSHost host, String spec) {
-        if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
-            throw new IllegalArgumentException("Bad intent tile spec: " + spec);
-        }
-        final String action = spec.substring(PREFIX.length(), spec.length() - 1);
-        if (action.isEmpty()) {
-            throw new IllegalArgumentException("Empty intent tile spec action");
-        }
-        return new IntentTile(host, action);
-    }
-
-    @Override
-    public void handleSetListening(boolean listening) {
-    }
-
-    @Override
-    public State newTileState() {
-        return new State();
-    }
-
-    @Override
-    protected void handleUserSwitch(int newUserId) {
-        super.handleUserSwitch(newUserId);
-        mCurrentUserId = newUserId;
-    }
-
-    @Override
-    protected void handleClick() {
-        sendIntent("click", mOnClick, mOnClickUri);
-    }
-
-    @Override
-    public Intent getLongClickIntent() {
-        return null;
-    }
-
-    @Override
-    protected void handleLongClick() {
-        sendIntent("long-click", mOnLongClick, mOnLongClickUri);
-    }
-
-    private void sendIntent(String type, PendingIntent pi, String uri) {
-        try {
-            if (pi != null) {
-                if (pi.isActivity()) {
-                    Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(pi);
-                } else {
-                    pi.send();
-                }
-            } else if (uri != null) {
-                final Intent intent = Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
-                mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
-            }
-        } catch (Throwable t) {
-            Log.w(TAG, "Error sending " + type + " intent", t);
-        }
-    }
-
-    @Override
-    public CharSequence getTileLabel() {
-        return getState().label;
-    }
-
-    @Override
-    protected void handleUpdateState(State state, Object arg) {
-        Intent intent = (Intent) arg;
-        if (intent == null) {
-            if (mLastIntent == null) {
-                return;
-            }
-            // No intent but need to refresh state, just use the last one.
-            intent = mLastIntent;
-        }
-        // Save the last one in case we need it later.
-        mLastIntent = intent;
-        state.contentDescription = intent.getStringExtra("contentDescription");
-        state.label = intent.getStringExtra("label");
-        state.icon = null;
-        final byte[] iconBitmap = intent.getByteArrayExtra("iconBitmap");
-        if (iconBitmap != null) {
-            try {
-                state.icon = new BytesIcon(iconBitmap);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error loading icon bitmap, length " + iconBitmap.length, t);
-            }
-        } else {
-            final int iconId = intent.getIntExtra("iconId", 0);
-            if (iconId != 0) {
-                final String iconPackage = intent.getStringExtra("iconPackage");
-                if (!TextUtils.isEmpty(iconPackage)) {
-                    state.icon = new PackageDrawableIcon(iconPackage, iconId);
-                } else {
-                    state.icon = ResourceIcon.get(iconId);
-                }
-            }
-        }
-        mOnClick = intent.getParcelableExtra("onClick");
-        mOnClickUri = intent.getStringExtra("onClickUri");
-        mOnLongClick = intent.getParcelableExtra("onLongClick");
-        mOnLongClickUri = intent.getStringExtra("onLongClickUri");
-        mIntentPackage = intent.getStringExtra("package");
-        mIntentPackage = mIntentPackage == null ? "" : mIntentPackage;
-    }
-
-    @Override
-    public int getMetricsCategory() {
-        return MetricsEvent.QS_INTENT;
-    }
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            refreshState(intent);
-        }
-    };
-
-    private static class BytesIcon extends Icon {
-        private final byte[] mBytes;
-
-        public BytesIcon(byte[] bytes) {
-            mBytes = bytes;
-        }
-
-        @Override
-        public Drawable getDrawable(Context context) {
-            final Bitmap b = BitmapFactory.decodeByteArray(mBytes, 0, mBytes.length);
-            return new BitmapDrawable(context.getResources(), b);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return o instanceof BytesIcon && Arrays.equals(((BytesIcon) o).mBytes, mBytes);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("BytesIcon[len=%s]", mBytes.length);
-        }
-    }
-
-    private class PackageDrawableIcon extends Icon {
-        private final String mPackage;
-        private final int mResId;
-
-        public PackageDrawableIcon(String pkg, int resId) {
-            mPackage = pkg;
-            mResId = resId;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (!(o instanceof PackageDrawableIcon)) return false;
-            final PackageDrawableIcon other = (PackageDrawableIcon) o;
-            return Objects.equals(other.mPackage, mPackage) && other.mResId == mResId;
-        }
-
-        @Override
-        public Drawable getDrawable(Context context) {
-            try {
-                return context.createPackageContext(mPackage, 0).getDrawable(mResId);
-            } catch (Throwable t) {
-                Log.w(TAG, "Error loading package drawable pkg=" + mPackage + " id=" + mResId, t);
-                return null;
-            }
-        }
-
-        @Override
-        public String toString() {
-            return String.format("PackageDrawableIcon[pkg=%s,id=0x%08x]", mPackage, mResId);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index d3ccbeb..77c3ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -27,7 +27,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import android.graphics.Point;
 import android.graphics.drawable.Icon;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
@@ -42,6 +41,7 @@
 import android.util.Log;
 import android.util.Size;
 import android.view.Surface;
+import android.view.WindowManager;
 import android.widget.Toast;
 
 import com.android.systemui.R;
@@ -76,7 +76,7 @@
     private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
 
     private static final int TOTAL_NUM_TRACKS = 1;
-    private static final int VIDEO_BIT_RATE = 6000000;
+    private static final int VIDEO_BIT_RATE = 10000000;
     private static final int VIDEO_FRAME_RATE = 30;
     private static final int AUDIO_BIT_RATE = 16;
     private static final int AUDIO_SAMPLE_RATE = 44100;
@@ -238,7 +238,9 @@
             mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
 
             // Set up video
-            DisplayMetrics metrics = getResources().getDisplayMetrics();
+            DisplayMetrics metrics = new DisplayMetrics();
+            WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+            wm.getDefaultDisplay().getRealMetrics(metrics);
             int screenWidth = metrics.widthPixels;
             int screenHeight = metrics.heightPixels;
             mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index c689ed1..03d9626 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -288,7 +288,14 @@
             boolean isTemporary) {
         mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary);
         synchronized (mLock) {
-            getServiceForUserLocked(userId).updateRemoteAugmentedAutofillService();
+            final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
+            if (service == null) {
+                // If we cannot get the service from the services cache, it will call
+                // updateRemoteAugmentedAutofillService() finally. Skip call this update again.
+                getServiceForUserLocked(userId);
+            } else {
+                service.updateRemoteAugmentedAutofillService();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 7d5b176..72e170f 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -63,6 +63,7 @@
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Class to keep track of the information related to "force app standby", which includes:
@@ -416,12 +417,12 @@
             }
             mStarted = true;
 
-            mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
-            mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
-            mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
-            mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
-            mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
-            mAppStandbyInternal = Preconditions.checkNotNull(injectAppStandbyInternal());
+            mIActivityManager = Objects.requireNonNull(injectIActivityManager());
+            mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal());
+            mAppOpsManager = Objects.requireNonNull(injectAppOpsManager());
+            mAppOpsService = Objects.requireNonNull(injectIAppOpsService());
+            mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal());
+            mAppStandbyInternal = Objects.requireNonNull(injectAppStandbyInternal());
 
             mFlagsObserver = new FeatureFlagsObserver();
             mFlagsObserver.register();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bb78ace..deac1e3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -47,8 +47,6 @@
 import static android.system.OsConstants.IPPROTO_TCP;
 import static android.system.OsConstants.IPPROTO_UDP;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
@@ -904,7 +902,7 @@
          * @see IpConnectivityMetrics.Logger
          */
         public IpConnectivityMetrics.Logger getMetricsLogger() {
-            return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
+            return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
                     "no IpConnectivityMetrics service");
         }
 
@@ -933,7 +931,7 @@
             IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) {
         if (DBG) log("ConnectivityService starting up");
 
-        mDeps = checkNotNull(deps, "missing Dependencies");
+        mDeps = Objects.requireNonNull(deps, "missing Dependencies");
         mSystemProperties = mDeps.getSystemProperties();
         mNetIdManager = mDeps.makeNetIdManager();
 
@@ -962,14 +960,14 @@
 
         mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
 
-        mContext = checkNotNull(context, "missing Context");
-        mNMS = checkNotNull(netManager, "missing INetworkManagementService");
-        mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
-        mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
-        mPolicyManagerInternal = checkNotNull(
+        mContext = Objects.requireNonNull(context, "missing Context");
+        mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
+        mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService");
+        mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager");
+        mPolicyManagerInternal = Objects.requireNonNull(
                 LocalServices.getService(NetworkPolicyManagerInternal.class),
                 "missing NetworkPolicyManagerInternal");
-        mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
+        mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver");
         mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
 
         mNetd = netd;
@@ -5195,7 +5193,7 @@
     @Override
     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
             PendingIntent operation) {
-        checkNotNull(operation, "PendingIntent cannot be null.");
+        Objects.requireNonNull(operation, "PendingIntent cannot be null.");
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
@@ -5222,7 +5220,7 @@
 
     @Override
     public void releasePendingNetworkRequest(PendingIntent operation) {
-        checkNotNull(operation, "PendingIntent cannot be null.");
+        Objects.requireNonNull(operation, "PendingIntent cannot be null.");
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT,
                 getCallingUid(), 0, operation));
     }
@@ -5280,7 +5278,7 @@
     @Override
     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
             PendingIntent operation) {
-        checkNotNull(operation, "PendingIntent cannot be null.");
+        Objects.requireNonNull(operation, "PendingIntent cannot be null.");
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/services/core/java/com/android/server/ExplicitHealthCheckController.java
index f7c4aac..77059d9 100644
--- a/services/core/java/com/android/server/ExplicitHealthCheckController.java
+++ b/services/core/java/com/android/server/ExplicitHealthCheckController.java
@@ -47,6 +47,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.Consumer;
 
@@ -113,9 +114,9 @@
                 Slog.wtf(TAG, "Resetting health check controller callbacks");
             }
 
-            mPassedConsumer = Preconditions.checkNotNull(passedConsumer);
-            mSupportedConsumer = Preconditions.checkNotNull(supportedConsumer);
-            mNotifySyncRunnable = Preconditions.checkNotNull(notifySyncRunnable);
+            mPassedConsumer = Objects.requireNonNull(passedConsumer);
+            mSupportedConsumer = Objects.requireNonNull(supportedConsumer);
+            mNotifySyncRunnable = Objects.requireNonNull(notifySyncRunnable);
         }
     }
 
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a629b3f..c987620 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -25,8 +25,6 @@
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -76,6 +74,7 @@
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A service to manage multiple clients that want to access the IpSec API. The service is
@@ -566,7 +565,7 @@
         }
 
         void put(int key, RefcountedResource<T> obj) {
-            checkNotNull(obj, "Null resources cannot be added");
+            Objects.requireNonNull(obj, "Null resources cannot be added");
             mArray.put(key, obj);
         }
 
@@ -1101,7 +1100,7 @@
         if (requestedSpi > 0 && requestedSpi < 256) {
             throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255.");
         }
-        checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
+        Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
 
         int callingUid = Binder.getCallingUid();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1218,7 +1217,7 @@
             throw new IllegalArgumentException(
                     "Specified port number must be a valid non-reserved UDP port");
         }
-        checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
+        Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
 
         int callingUid = Binder.getCallingUid();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1278,8 +1277,8 @@
             String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
             String callingPackage) {
         enforceTunnelFeatureAndPermissions(callingPackage);
-        checkNotNull(binder, "Null Binder passed to createTunnelInterface");
-        checkNotNull(underlyingNetwork, "No underlying network was specified");
+        Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface");
+        Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
         checkInetAddress(localAddr);
         checkInetAddress(remoteAddr);
 
@@ -1556,7 +1555,7 @@
                     "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
         }
 
-        checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
+        Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels");
         switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
             case AppOpsManager.MODE_DEFAULT:
                 mContext.enforceCallingOrSelfPermission(
@@ -1625,12 +1624,12 @@
     @Override
     public synchronized IpSecTransformResponse createTransform(
             IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
-        checkNotNull(c);
+        Objects.requireNonNull(c);
         if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
             enforceTunnelFeatureAndPermissions(callingPackage);
         }
         checkIpSecConfig(c);
-        checkNotNull(binder, "Null Binder passed to createTransform");
+        Objects.requireNonNull(binder, "Null Binder passed to createTransform");
         final int resourceId = mNextResourceId++;
 
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index cad917b..c5f1923 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -23,7 +23,6 @@
 import static android.location.LocationManager.PASSIVE_PROVIDER;
 import static android.os.PowerManager.locationPowerSaveModeToString;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkState;
 
 import android.Manifest;
@@ -121,6 +120,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -821,7 +821,7 @@
 
         @GuardedBy("mLock")
         public void attachLocked(AbstractLocationProvider provider) {
-            checkNotNull(provider);
+            Objects.requireNonNull(provider);
             checkState(mProvider == null);
 
             if (D) {
@@ -1430,7 +1430,7 @@
     @Override
     public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
             String featureId, String listenerIdentifier) {
-        Preconditions.checkNotNull(listenerIdentifier);
+        Objects.requireNonNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false : mGnssManagerService.addGnssBatchingCallback(
                 callback, packageName, featureId, listenerIdentifier);
@@ -2119,7 +2119,7 @@
     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
             PendingIntent intent, String packageName, String featureId,
             String listenerIdentifier) {
-        Preconditions.checkNotNull(listenerIdentifier);
+        Objects.requireNonNull(listenerIdentifier);
 
         synchronized (mLock) {
             if (request == null) request = DEFAULT_LOCATION_REQUEST;
@@ -2470,7 +2470,7 @@
     @Override
     public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
             String packageName, String featureId, String listenerIdentifier) {
-        Preconditions.checkNotNull(listenerIdentifier);
+        Objects.requireNonNull(listenerIdentifier);
 
         if (request == null) request = DEFAULT_LOCATION_REQUEST;
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
@@ -2567,7 +2567,7 @@
     @Override
     public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
             String packageName, String featureId, String listenerIdentifier) {
-        Preconditions.checkNotNull(listenerIdentifier);
+        Objects.requireNonNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false
                 : mGnssManagerService.addGnssMeasurementsListener(listener, packageName, featureId,
@@ -2600,7 +2600,7 @@
     @Override
     public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
             String packageName, String featureId, String listenerIdentifier) {
-        Preconditions.checkNotNull(listenerIdentifier);
+        Objects.requireNonNull(listenerIdentifier);
 
         return mGnssManagerService == null ? false
                 : mGnssManagerService.addGnssNavigationMessageListener(listener, packageName,
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index ad02aad..eac767f 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -46,6 +46,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.LinkedList;
+import java.util.Objects;
 
 /**
  * Generic connector class for interfacing with a native daemon which uses the
@@ -126,7 +127,7 @@
      */
     public void setWarnIfHeld(Object warnIfHeld) {
         Preconditions.checkState(mWarnIfHeld == null);
-        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+        mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0d496b6..1f73650 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -109,6 +109,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * @hide
@@ -456,7 +457,7 @@
     @Override
     public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
         NetworkStack.checkNetworkStackPermission(mContext);
-        Preconditions.checkNotNull(provider);
+        Objects.requireNonNull(provider);
         synchronized(mTetheringStatsProviders) {
             mTetheringStatsProviders.put(provider, name);
         }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 22fa8ff4..c474f47 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2102,7 +2102,7 @@
     public void setVolumeNickname(String fsUuid, String nickname) {
         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
-        Preconditions.checkNotNull(fsUuid);
+        Objects.requireNonNull(fsUuid);
         synchronized (mLock) {
             final VolumeRecord rec = mRecords.get(fsUuid);
             rec.nickname = nickname;
@@ -2115,7 +2115,7 @@
     public void setVolumeUserFlags(String fsUuid, int flags, int mask) {
         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
-        Preconditions.checkNotNull(fsUuid);
+        Objects.requireNonNull(fsUuid);
         synchronized (mLock) {
             final VolumeRecord rec = mRecords.get(fsUuid);
             rec.userFlags = (rec.userFlags & ~mask) | (flags & mask);
@@ -2128,7 +2128,7 @@
     public void forgetVolume(String fsUuid) {
         enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
 
-        Preconditions.checkNotNull(fsUuid);
+        Objects.requireNonNull(fsUuid);
 
         synchronized (mLock) {
             final VolumeRecord rec = mRecords.remove(fsUuid);
@@ -2534,7 +2534,7 @@
 
     @Override
     public String getMountedObbPath(String rawPath) {
-        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Objects.requireNonNull(rawPath, "rawPath cannot be null");
 
         warnOnNotMounted();
 
@@ -2552,7 +2552,7 @@
 
     @Override
     public boolean isObbMounted(String rawPath) {
-        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Objects.requireNonNull(rawPath, "rawPath cannot be null");
         synchronized (mObbMounts) {
             return mObbPathToStateMap.containsKey(rawPath);
         }
@@ -2561,10 +2561,10 @@
     @Override
     public void mountObb(String rawPath, String canonicalPath, String key,
             IObbActionListener token, int nonce, ObbInfo obbInfo) {
-        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
-        Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
-        Preconditions.checkNotNull(token, "token cannot be null");
-        Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
+        Objects.requireNonNull(rawPath, "rawPath cannot be null");
+        Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null");
+        Objects.requireNonNull(token, "token cannot be null");
+        Objects.requireNonNull(obbInfo, "obbIfno cannot be null");
 
         final int callingUid = Binder.getCallingUid();
         final ObbState obbState = new ObbState(rawPath, canonicalPath,
@@ -2578,7 +2578,7 @@
 
     @Override
     public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) {
-        Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
+        Objects.requireNonNull(rawPath, "rawPath cannot be null");
 
         final ObbState existingState;
         synchronized (mObbMounts) {
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index 5ed94e3..179780d 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -28,6 +28,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
@@ -73,7 +74,7 @@
      */
     public static @NonNull Future<?> submit(@NonNull Runnable runnable,
             @NonNull String description) {
-        Preconditions.checkNotNull(description, "description cannot be null");
+        Objects.requireNonNull(description, "description cannot be null");
 
         SystemServerInitThreadPool instance;
         synchronized (LOCK) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index c741fce..783715c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -785,9 +785,11 @@
                             if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 r.callback.onServiceStateChanged(rawSs);
                             } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+                                r.callback.onServiceStateChanged(
+                                        rawSs.createLocationInfoSanitizedCopy(false));
                             } else {
-                                r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+                                r.callback.onServiceStateChanged(
+                                        rawSs.createLocationInfoSanitizedCopy(true));
                             }
                         } catch (RemoteException ex) {
                             remove(r.binder);
@@ -1142,9 +1144,9 @@
                             if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 stateToSend = new ServiceState(state);
                             } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                stateToSend = state.sanitizeLocationInfo(false);
+                                stateToSend = state.createLocationInfoSanitizedCopy(false);
                             } else {
-                                stateToSend = state.sanitizeLocationInfo(true);
+                                stateToSend = state.createLocationInfoSanitizedCopy(true);
                             }
                             if (DBG) {
                                 log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index d19d2dd..c27b0da 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -16,8 +16,6 @@
 
 package com.android.server;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -55,6 +53,7 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /** @hide */
@@ -82,9 +81,9 @@
         mHandlerThread.start();
         mHandler = new Handler(mHandlerThread.getLooper());
 
-        mContext = checkNotNull(context, "missing Context");
-        mNMS = checkNotNull(netManager, "missing INetworkManagementService");
-        mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance");
+        mContext = Objects.requireNonNull(context, "missing Context");
+        mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
+        mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance");
     }
 
     /**
@@ -96,7 +95,7 @@
     private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
         enforceTestNetworkPermissions(mContext);
 
-        checkNotNull(linkAddrs, "missing linkAddrs");
+        Objects.requireNonNull(linkAddrs, "missing linkAddrs");
 
         String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
         String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
@@ -233,8 +232,8 @@
             int callingUid,
             @NonNull IBinder binder)
             throws RemoteException, SocketException {
-        checkNotNull(looper, "missing Looper");
-        checkNotNull(context, "missing Context");
+        Objects.requireNonNull(looper, "missing Looper");
+        Objects.requireNonNull(context, "missing Context");
         // iface and binder validity checked by caller
 
         // Build network info with special testing type
@@ -267,7 +266,7 @@
         // Find the currently assigned addresses, and add them to LinkProperties
         boolean allowIPv4 = false, allowIPv6 = false;
         NetworkInterface netIntf = NetworkInterface.getByName(iface);
-        checkNotNull(netIntf, "No such network interface found: " + netIntf);
+        Objects.requireNonNull(netIntf, "No such network interface found: " + netIntf);
 
         for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
             lp.addLinkAddress(
@@ -305,8 +304,8 @@
             @NonNull IBinder binder) {
         enforceTestNetworkPermissions(mContext);
 
-        checkNotNull(iface, "missing Iface");
-        checkNotNull(binder, "missing IBinder");
+        Objects.requireNonNull(iface, "missing Iface");
+        Objects.requireNonNull(binder, "missing IBinder");
 
         if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX)
                 || iface.startsWith(TEST_TUN_PREFIX))) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5996b7d..a372fca0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -463,7 +463,7 @@
             Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
                     callingUid, account.type);
@@ -544,7 +544,7 @@
 
     @Override
     public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         int callingUid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -590,8 +590,8 @@
 
     @Override
     public int getAccountVisibility(Account account, String packageName) {
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(packageName, "packageName cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(packageName, "packageName cannot be null");
         int callingUid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -659,7 +659,7 @@
      */
     private Integer resolveAccountVisibility(Account account, @NonNull String packageName,
             UserAccounts accounts) {
-        Preconditions.checkNotNull(packageName, "packageName cannot be null");
+        Objects.requireNonNull(packageName, "packageName cannot be null");
         int uid = -1;
         try {
             long identityToken = clearCallingIdentity();
@@ -755,8 +755,8 @@
 
     @Override
     public boolean setAccountVisibility(Account account, String packageName, int newVisibility) {
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(packageName, "packageName cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(packageName, "packageName cannot be null");
         int callingUid = Binder.getCallingUid();
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)
@@ -1525,7 +1525,7 @@
                     + ", caller's uid " + Binder.getCallingUid()
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
@@ -1563,8 +1563,8 @@
                     account, key, callingUid, Binder.getCallingPid());
             Log.v(TAG, msg);
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(key, "key cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(key, "key cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -1715,7 +1715,7 @@
                     callingUid);
             Log.v(TAG, msg);
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -2401,8 +2401,8 @@
     @Override
     public void invalidateAuthToken(String accountType, String authToken) {
         int callerUid = Binder.getCallingUid();
-        Preconditions.checkNotNull(accountType, "accountType cannot be null");
-        Preconditions.checkNotNull(authToken, "authToken cannot be null");
+        Objects.requireNonNull(accountType, "accountType cannot be null");
+        Objects.requireNonNull(authToken, "authToken cannot be null");
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "invalidateAuthToken: accountType " + accountType
                     + ", caller's uid " + callerUid
@@ -2518,8 +2518,8 @@
                     + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(authTokenType, "authTokenType cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(authTokenType, "authTokenType cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -2551,8 +2551,8 @@
                     + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(authTokenType, "authTokenType cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(authTokenType, "authTokenType cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -2578,7 +2578,7 @@
                     + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -2644,7 +2644,7 @@
                     + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
         int userId = UserHandle.getCallingUserId();
         if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
@@ -3946,9 +3946,9 @@
         if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
             throw new SecurityException("Can be called only by system UID");
         }
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(packageName, "packageName cannot be null");
-        Preconditions.checkNotNull(userHandle, "userHandle cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(packageName, "packageName cannot be null");
+        Objects.requireNonNull(userHandle, "userHandle cannot be null");
 
         final int userId = userHandle.getIdentifier();
 
@@ -4022,9 +4022,9 @@
             throw new SecurityException("Can be called only by system UID");
         }
 
-        Preconditions.checkNotNull(account, "account cannot be null");
-        Preconditions.checkNotNull(packageName, "packageName cannot be null");
-        Preconditions.checkNotNull(userHandle, "userHandle cannot be null");
+        Objects.requireNonNull(account, "account cannot be null");
+        Objects.requireNonNull(packageName, "packageName cannot be null");
+        Objects.requireNonNull(userHandle, "userHandle cannot be null");
 
         final int userId = userHandle.getIdentifier();
 
diff --git a/services/core/java/com/android/server/accounts/CryptoHelper.java b/services/core/java/com/android/server/accounts/CryptoHelper.java
index 2ade673..863d6b9 100644
--- a/services/core/java/com/android/server/accounts/CryptoHelper.java
+++ b/services/core/java/com/android/server/accounts/CryptoHelper.java
@@ -10,6 +10,7 @@
 
 import java.security.GeneralSecurityException;
 import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
 
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
@@ -54,7 +55,7 @@
 
     @NonNull
     /* default */ Bundle encryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
-        Preconditions.checkNotNull(bundle, "Cannot encrypt null bundle.");
+        Objects.requireNonNull(bundle, "Cannot encrypt null bundle.");
         Parcel parcel = Parcel.obtain();
         bundle.writeToParcel(parcel, 0);
         byte[] clearBytes = parcel.marshall();
@@ -76,7 +77,7 @@
 
     @Nullable
     /* default */ Bundle decryptBundle(@NonNull Bundle bundle) throws GeneralSecurityException {
-        Preconditions.checkNotNull(bundle, "Cannot decrypt null bundle.");
+        Objects.requireNonNull(bundle, "Cannot decrypt null bundle.");
         byte[] iv = bundle.getByteArray(KEY_IV);
         byte[] encryptedBytes = bundle.getByteArray(KEY_CIPHER);
         byte[] mac = bundle.getByteArray(KEY_MAC);
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
index 2af2f38..e38cf5f 100644
--- a/services/core/java/com/android/server/accounts/TokenCache.java
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -193,7 +193,7 @@
             String packageName,
             byte[] sigDigest,
             long expiryMillis) {
-        Preconditions.checkNotNull(account);
+        Objects.requireNonNull(account);
         if (token == null || System.currentTimeMillis() > expiryMillis) {
             return;
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 79fe610..a4c44fa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -111,6 +111,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -1785,7 +1786,7 @@
     }
 
     int runGetCurrentUser(PrintWriter pw) throws RemoteException {
-        UserInfo currentUser = Preconditions.checkNotNull(mInterface.getCurrentUser(),
+        UserInfo currentUser = Objects.requireNonNull(mInterface.getCurrentUser(),
                 "Current user not set");
         pw.println(currentUser.id);
         return 0;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f9730a9..eb1ab38 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1723,7 +1723,7 @@
     }
 
     void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
-        Preconditions.checkNotNull(name, "Observer name cannot be null");
+        Objects.requireNonNull(name, "Observer name cannot be null");
         checkCallingPermission(INTERACT_ACROSS_USERS_FULL, "registerUserSwitchObserver");
         mUserSwitchObservers.register(observer, name);
     }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 9f23cdaf..7ef84bd 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -477,9 +477,12 @@
 
     /** A in progress startOp->finishOp event */
     private static final class InProgressStartOpEvent implements IBinder.DeathRecipient {
-        /** Time of startOp event */
+        /** Wall clock time of startOp event (not monotonic) */
         final long startTime;
 
+        /** Elapsed time since boot of startOp event */
+        final long startElapsedTime;
+
         /** Id of the client that started the event */
         final @NonNull IBinder clientId;
 
@@ -492,9 +495,11 @@
         /** How many times the op was started but not finished yet */
         int numUnfinishedStarts;
 
-        private InProgressStartOpEvent(long startTime, @NonNull IBinder clientId,
-                @NonNull Runnable onDeath, int uidState) throws RemoteException {
+        private InProgressStartOpEvent(long startTime, long startElapsedTime,
+                @NonNull IBinder clientId, @NonNull Runnable onDeath, int uidState)
+                throws RemoteException {
             this.startTime = startTime;
+            this.startElapsedTime = startElapsedTime;
             this.clientId = clientId;
             this.onDeath = onDeath;
             this.uidState = uidState;
@@ -636,7 +641,8 @@
 
             InProgressStartOpEvent event = mInProgressEvents.get(clientId);
             if (event == null) {
-                event = new InProgressStartOpEvent(System.currentTimeMillis(), clientId, () -> {
+                event = new InProgressStartOpEvent(System.currentTimeMillis(),
+                        SystemClock.elapsedRealtime(), clientId, () -> {
                     // In the case the client dies without calling finish first
                     synchronized (AppOpsService.this) {
                         if (mInProgressEvents == null) {
@@ -698,7 +704,7 @@
 
                 // startOp events don't support proxy, hence use flags==SELF
                 NoteOpEvent finishedEvent = new NoteOpEvent(event.startTime,
-                        System.currentTimeMillis() - event.startTime, null);
+                        SystemClock.elapsedRealtime() - event.startElapsedTime, null);
                 mAccessEvents.put(makeKey(event.uidState, OP_FLAG_SELF), finishedEvent);
 
                 mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
@@ -759,7 +765,7 @@
 
             // Add in progress events as access events
             if (mInProgressEvents != null) {
-                long now = System.currentTimeMillis();
+                long now = SystemClock.elapsedRealtime();
                 int numInProgressEvents = mInProgressEvents.size();
 
                 if (accessEvents == null) {
@@ -771,7 +777,7 @@
 
                     // startOp events don't support proxy
                     accessEvents.append(makeKey(event.uidState, OP_FLAG_SELF),
-                            new NoteOpEvent(event.startTime, now - event.startTime, null));
+                            new NoteOpEvent(event.startTime, now - event.startElapsedTime, null));
                 }
             }
 
@@ -1411,7 +1417,7 @@
                 .setOpNames(opNames)
                 .setFlags(flags)
                 .build();
-        Preconditions.checkNotNull(callback, "callback cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
 
         mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
@@ -1436,7 +1442,7 @@
                 .setOpNames(opNames)
                 .setFlags(flags)
                 .build();
-        Preconditions.checkNotNull(callback, "callback cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
 
         mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
                 Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
@@ -2212,7 +2218,7 @@
 
     @Override
     public int checkPackage(int uid, String packageName) {
-        Preconditions.checkNotNull(packageName);
+        Objects.requireNonNull(packageName);
         try {
             verifyAndGetIsPrivileged(uid, packageName);
 
@@ -2419,7 +2425,7 @@
         Preconditions.checkArgument(!ArrayUtils.isEmpty(ops), "Ops cannot be null or empty");
         Preconditions.checkArrayElementsInRange(ops, 0, AppOpsManager._NUM_OP - 1,
                 "Invalid op code in: " + Arrays.toString(ops));
-        Preconditions.checkNotNull(callback, "Callback cannot be null");
+        Objects.requireNonNull(callback, "Callback cannot be null");
         synchronized (this) {
             SparseArray<NotedCallback> callbacks = mNotedWatchers.get(callback.asBinder());
             if (callbacks == null) {
@@ -2436,7 +2442,7 @@
 
     @Override
     public void stopWatchingNoted(IAppOpsNotedCallback callback) {
-        Preconditions.checkNotNull(callback, "Callback cannot be null");
+        Objects.requireNonNull(callback, "Callback cannot be null");
         synchronized (this) {
             final SparseArray<NotedCallback> notedCallbacks =
                     mNotedWatchers.remove(callback.asBinder());
@@ -2453,7 +2459,7 @@
     @Override
     public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
             String featureId, String message) {
-        Preconditions.checkNotNull(message);
+        Objects.requireNonNull(message);
         verifyAndGetIsPrivileged(uid, packageName);
 
         verifyIncomingUid(uid);
@@ -2522,8 +2528,8 @@
 
     @Override
     public void startWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(callback);
 
         int uid = Binder.getCallingUid();
         Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
@@ -2552,8 +2558,8 @@
 
     @Override
     public void stopWatchingAsyncNoted(String packageName, IAppOpsAsyncNotedCallback callback) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(callback);
 
         int uid = Binder.getCallingUid();
         Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
@@ -2573,7 +2579,7 @@
 
     @Override
     public List<AsyncNotedAppOp> extractAsyncOps(String packageName) {
-        Preconditions.checkNotNull(packageName);
+        Objects.requireNonNull(packageName);
 
         int uid = Binder.getCallingUid();
 
@@ -4188,18 +4194,18 @@
 
         final FeatureOp featureOp = op.mFeatures.get(featureId);
         if (featureOp.isRunning()) {
-            long earliestStartTime = Long.MAX_VALUE;
+            long earliestElapsedTime = Long.MAX_VALUE;
             long maxNumStarts = 0;
             int numInProgressEvents = featureOp.mInProgressEvents.size();
             for (int i = 0; i < numInProgressEvents; i++) {
                 InProgressStartOpEvent event = featureOp.mInProgressEvents.valueAt(i);
 
-                earliestStartTime = Math.min(earliestStartTime, event.startTime);
+                earliestElapsedTime = Math.min(earliestElapsedTime, event.startElapsedTime);
                 maxNumStarts = Math.max(maxNumStarts, event.numUnfinishedStarts);
             }
 
             pw.print(prefix + "Running start at: ");
-            TimeUtils.formatDuration(nowElapsed - earliestStartTime, pw);
+            TimeUtils.formatDuration(nowElapsed - earliestElapsedTime, pw);
             pw.println();
 
             if (maxNumStarts > 1) {
@@ -4471,7 +4477,7 @@
                 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
                     boolean hasOp = dumpOp < 0 || (uidState.opModes != null
                             && uidState.opModes.indexOfKey(dumpOp) >= 0);
-                    boolean hasPackage = dumpPackage == null;
+                    boolean hasPackage = dumpPackage == null || dumpUid == mUidStates.keyAt(i);
                     boolean hasMode = dumpMode < 0;
                     if (!hasMode && opModes != null) {
                         for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
@@ -4702,8 +4708,8 @@
     @Override
     public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
         checkSystemUid("setUserRestrictions");
-        Preconditions.checkNotNull(restrictions);
-        Preconditions.checkNotNull(token);
+        Objects.requireNonNull(restrictions);
+        Objects.requireNonNull(token);
         for (int i = 0; i < AppOpsManager._NUM_OP; i++) {
             String restriction = AppOpsManager.opToRestriction(i);
             if (restriction != null) {
@@ -4730,7 +4736,7 @@
             }
         }
         verifyIncomingOp(code);
-        Preconditions.checkNotNull(token);
+        Objects.requireNonNull(token);
         setUserRestrictionNoCheck(code, restricted, token, userHandle, exceptionPackages);
     }
 
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index fc67e24..5ac5b29 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -67,6 +67,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * An attention service implementation that runs in System Server process.
@@ -120,7 +121,7 @@
     AttentionManagerService(Context context, PowerManager powerManager, Object lock,
             AttentionHandler handler) {
         super(context);
-        mContext = Preconditions.checkNotNull(context);
+        mContext = Objects.requireNonNull(context);
         mPowerManager = powerManager;
         mLock = lock;
         mAttentionHandler = handler;
@@ -200,7 +201,7 @@
      */
     @VisibleForTesting
     boolean checkAttention(long timeout, AttentionCallbackInternal callbackInternal) {
-        Preconditions.checkNotNull(callbackInternal);
+        Objects.requireNonNull(callbackInternal);
 
         if (!isAttentionServiceSupported()) {
             Slog.w(LOG_TAG, "Trying to call checkAttention() on an unsupported device.");
@@ -543,9 +544,9 @@
         UserState(int userId, Context context, Object lock, Handler handler,
                 ComponentName componentName) {
             mUserId = userId;
-            mContext = Preconditions.checkNotNull(context);
-            mLock = Preconditions.checkNotNull(lock);
-            mComponentName = Preconditions.checkNotNull(componentName);
+            mContext = Objects.requireNonNull(context);
+            mLock = Objects.requireNonNull(lock);
+            mComponentName = Objects.requireNonNull(componentName);
             mAttentionHandler = handler;
         }
 
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 114aac9..bc4dc8f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2196,7 +2196,7 @@
     public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags,
                                             String callingPackage) {
         enforceModifyAudioRoutingPermission();
-        Preconditions.checkNotNull(attr, "attr must not be null");
+        Objects.requireNonNull(attr, "attr must not be null");
         // @todo not hold the caller context, post message
         int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
         final int device = getDeviceForStream(stream);
@@ -2231,7 +2231,7 @@
     /** @see AudioManager#getVolumeIndexForAttributes(attr) */
     public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
         enforceModifyAudioRoutingPermission();
-        Preconditions.checkNotNull(attr, "attr must not be null");
+        Objects.requireNonNull(attr, "attr must not be null");
         int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
         final int device = getDeviceForStream(stream);
 
@@ -2241,14 +2241,14 @@
     /** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
     public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
         enforceModifyAudioRoutingPermission();
-        Preconditions.checkNotNull(attr, "attr must not be null");
+        Objects.requireNonNull(attr, "attr must not be null");
         return AudioSystem.getMaxVolumeIndexForAttributes(attr);
     }
 
     /** @see AudioManager#getMinVolumeIndexForAttributes(attr) */
     public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
         enforceModifyAudioRoutingPermission();
-        Preconditions.checkNotNull(attr, "attr must not be null");
+        Objects.requireNonNull(attr, "attr must not be null");
         return AudioSystem.getMinVolumeIndexForAttributes(attr);
     }
 
@@ -2510,7 +2510,7 @@
 
 
     private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
-        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        Objects.requireNonNull(attributes, "attributes must not be null");
         int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
         if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
             return volumeGroupId;
@@ -2521,7 +2521,7 @@
     }
 
     private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
-        Preconditions.checkNotNull(attributes, "attributes must not be null");
+        Objects.requireNonNull(attributes, "attributes must not be null");
         for (final AudioProductStrategy productStrategy :
                 AudioProductStrategy.getAudioProductStrategies()) {
             int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index ff0b015..28f67fe 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -34,6 +34,7 @@
 
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * A utility to map from an ambient brightness to a display's "backlight" brightness based on the
@@ -702,7 +703,7 @@
                     "Nits and backlight arrays must not be empty!");
             Preconditions.checkArgument(nits.length == backlight.length,
                     "Nits and backlight arrays must be the same length!");
-            Preconditions.checkNotNull(config);
+            Objects.requireNonNull(config);
             Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
             Preconditions.checkArrayElementsInRange(backlight,
                     PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
diff --git a/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java b/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
index 1707a62..75d00ff 100644
--- a/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
+++ b/services/core/java/com/android/server/display/whitebalance/AmbientSensor.java
@@ -29,6 +29,7 @@
 import com.android.server.display.utils.History;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * The DisplayWhiteBalanceController uses the AmbientSensor to detect changes in the ambient
@@ -139,8 +140,8 @@
 
 
     private static void validateArguments(Handler handler, SensorManager sensorManager, int rate) {
-        Preconditions.checkNotNull(handler, "handler cannot be null");
-        Preconditions.checkNotNull(sensorManager, "sensorManager cannot be null");
+        Objects.requireNonNull(handler, "handler cannot be null");
+        Objects.requireNonNull(sensorManager, "sensorManager cannot be null");
         if (rate <= 0) {
             throw new IllegalArgumentException("rate must be positive");
         }
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index 88a7077..d64fcbc 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -28,6 +28,7 @@
 import com.android.server.display.utils.History;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * The DisplayWhiteBalanceController drives display white-balance (automatically correcting the
@@ -475,13 +476,13 @@
             AmbientSensor.AmbientColorTemperatureSensor colorTemperatureSensor,
             AmbientFilter colorTemperatureFilter,
             DisplayWhiteBalanceThrottler throttler) {
-        Preconditions.checkNotNull(brightnessSensor, "brightnessSensor must not be null");
-        Preconditions.checkNotNull(brightnessFilter, "brightnessFilter must not be null");
-        Preconditions.checkNotNull(colorTemperatureSensor,
+        Objects.requireNonNull(brightnessSensor, "brightnessSensor must not be null");
+        Objects.requireNonNull(brightnessFilter, "brightnessFilter must not be null");
+        Objects.requireNonNull(colorTemperatureSensor,
                 "colorTemperatureSensor must not be null");
-        Preconditions.checkNotNull(colorTemperatureFilter,
+        Objects.requireNonNull(colorTemperatureFilter,
                 "colorTemperatureFilter must not be null");
-        Preconditions.checkNotNull(throttler, "throttler cannot be null");
+        Objects.requireNonNull(throttler, "throttler cannot be null");
     }
 
     private boolean enable() {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
index 6e78894..0efb749 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
@@ -30,6 +30,7 @@
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController.Callbacks;
 
 import java.io.PrintWriter;
+import java.util.Objects;
 
 /**
  * The DisplayWhiteBalanceSettings holds the state of all the settings related to
@@ -144,8 +145,8 @@
     }
 
     private void validateArguments(Context context, Handler handler) {
-        Preconditions.checkNotNull(context, "context must not be null");
-        Preconditions.checkNotNull(handler, "handler must not be null");
+        Objects.requireNonNull(context, "context must not be null");
+        Objects.requireNonNull(handler, "handler must not be null");
     }
 
     private void setEnabled(boolean enabled) {
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index f3d60f5..b1639a9 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -196,6 +196,15 @@
 
     private void handleIntegrityVerification(Intent intent) {
         int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
+
+        // Fail early if we don't have any rules at all.
+        if (!mIntegrityFileManager.initialized()) {
+            Slog.i(TAG, "Rules not initialized. Skipping integrity check.");
+            mPackageManagerInternal.setIntegrityVerificationResult(
+                    verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+            return;
+        }
+
         try {
             Slog.i(TAG, "Received integrity verification intent " + intent.toString());
             Slog.i(TAG, "Extras " + intent.getExtras());
@@ -376,6 +385,9 @@
                         String packageName = getPackageNameNormalized(packageAndCert[0]);
                         String cert = packageAndCert[1];
                         packageCertMap.put(packageName, cert);
+                    } else if (packageAndCert.length == 1
+                            && packageAndCert[0].equals(ADB_INSTALLER)) {
+                        packageCertMap.put(ADB_INSTALLER, INSTALLER_CERT_NOT_APPLICABLE);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
index e224724..30cafaa 100644
--- a/services/core/java/com/android/server/integrity/IntegrityFileManager.java
+++ b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
@@ -24,14 +24,14 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.integrity.model.RuleMetadata;
+import com.android.server.integrity.parser.RuleBinaryParser;
 import com.android.server.integrity.parser.RuleMetadataParser;
 import com.android.server.integrity.parser.RuleParseException;
 import com.android.server.integrity.parser.RuleParser;
-import com.android.server.integrity.parser.RuleXmlParser;
+import com.android.server.integrity.serializer.RuleBinarySerializer;
 import com.android.server.integrity.serializer.RuleMetadataSerializer;
 import com.android.server.integrity.serializer.RuleSerializeException;
 import com.android.server.integrity.serializer.RuleSerializer;
-import com.android.server.integrity.serializer.RuleXmlSerializer;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -57,6 +57,7 @@
     private final RuleParser mRuleParser;
     private final RuleSerializer mRuleSerializer;
 
+    private final File mDataDir;
     // mRulesDir contains data of the actual rules currently stored.
     private final File mRulesDir;
     // mStagingDir is used to store the temporary rules / metadata during updating, since we want to
@@ -75,8 +76,8 @@
 
     private IntegrityFileManager() {
         this(
-                new RuleXmlParser(),
-                new RuleXmlSerializer(),
+                new RuleBinaryParser(),
+                new RuleBinarySerializer(),
                 Environment.getDataSystemDirectory());
     }
 
@@ -84,11 +85,12 @@
     IntegrityFileManager(RuleParser ruleParser, RuleSerializer ruleSerializer, File dataDir) {
         mRuleParser = ruleParser;
         mRuleSerializer = ruleSerializer;
+        mDataDir = dataDir;
 
         mRulesDir = new File(dataDir, "integrity_rules");
         mStagingDir = new File(dataDir, "integrity_staging");
 
-        if (!mStagingDir.mkdirs() && mRulesDir.mkdirs()) {
+        if (!mStagingDir.mkdirs() || !mRulesDir.mkdirs()) {
             Slog.e(TAG, "Error creating staging and rules directory");
             // TODO: maybe throw an exception?
         }
@@ -103,6 +105,16 @@
         }
     }
 
+    /**
+     * Returns if the rules have been initialized.
+     *
+     * <p>Used to fail early if there are no rules (so we don't need to parse the apk at all).
+     */
+    public boolean initialized() {
+        return new File(mRulesDir, RULES_FILE).exists()
+                && new File(mRulesDir, METADATA_FILE).exists();
+    }
+
     /** Write rules to persistent storage. */
     public void writeRules(String version, String ruleProvider, List<Rule> rules)
             throws IOException, RuleSerializeException {
@@ -146,7 +158,7 @@
 
     private void switchStagingRulesDir() throws IOException {
         synchronized (RULES_LOCK) {
-            File tmpDir = new File(Environment.getDataSystemDirectory(), "temp");
+            File tmpDir = new File(mDataDir, "temp");
 
             if (!(mRulesDir.renameTo(tmpDir)
                     && mStagingDir.renameTo(mRulesDir)
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index 25defb0..22af085 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -36,6 +36,7 @@
 import android.content.integrity.Formula;
 import android.content.integrity.Rule;
 
+import com.android.internal.util.Preconditions;
 import com.android.server.integrity.IntegrityUtils;
 import com.android.server.integrity.model.BitOutputStream;
 
@@ -46,10 +47,17 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.TreeMap;
 
 /** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
 public class RuleBinarySerializer implements RuleSerializer {
 
+    // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format.
+    private static final int INDEXING_BLOCK_SIZE = 100;
+
+    private static final String START_INDEXING_KEY = "START_KEY";
+    private static final String END_INDEXING_KEY = "END_KEY";
+
     // Get the byte representation for a list of rules.
     @Override
     public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
@@ -66,25 +74,34 @@
     // Get the byte representation for a list of rules, and write them to an output stream.
     @Override
     public void serialize(
-            List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
+            List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream)
             throws RuleSerializeException {
         try {
             // Determine the indexing groups and the order of the rules within each indexed group.
-            Map<Integer, List<Rule>> indexedRules =
+            Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
                     RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
 
+            ByteTrackedOutputStream outputStream =
+                    new ByteTrackedOutputStream(originalOutputStream);
+
             serializeRuleFileMetadata(formatVersion, outputStream);
 
-            serializeIndexedRules(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
-            serializeIndexedRules(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
-            serializeIndexedRules(indexedRules.get(NOT_INDEXED), outputStream);
+            Map<String, Long> packageNameIndexes =
+                    serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
+            Map<String, Long> appCertificateIndexes =
+                    serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
+            Map<String, Long> unindexedRulesIndex =
+                    serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream);
+
+            // TODO(b/145493956): Write these indexes into a index file provided by integrity file
+            //  manager.
         } catch (Exception e) {
             throw new RuleSerializeException(e.getMessage(), e);
         }
     }
 
-    private void serializeRuleFileMetadata(
-            Optional<Integer> formatVersion, OutputStream outputStream) throws IOException {
+    private void serializeRuleFileMetadata(Optional<Integer> formatVersion,
+            ByteTrackedOutputStream outputStream) throws IOException {
         int formatVersionValue = formatVersion.orElse(DEFAULT_FORMAT_VERSION);
 
         BitOutputStream bitOutputStream = new BitOutputStream();
@@ -92,17 +109,33 @@
         outputStream.write(bitOutputStream.toByteArray());
     }
 
-    private void serializeIndexedRules(List<Rule> rules, OutputStream outputStream)
+    private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+            ByteTrackedOutputStream outputStream)
             throws IOException {
-        if (rules == null) {
-            return;
-        }
+        Preconditions.checkArgument(rulesMap != null,
+                "serializeRuleList should never be called with null rule list.");
+
         BitOutputStream bitOutputStream = new BitOutputStream();
-        for (Rule rule : rules) {
-            bitOutputStream.clear();
-            serializeRule(rule, bitOutputStream);
-            outputStream.write(bitOutputStream.toByteArray());
+        Map<String, Long> indexMapping = new TreeMap();
+        long indexTracker = 0;
+
+        indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount());
+        for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+            if (indexTracker >= INDEXING_BLOCK_SIZE) {
+                indexMapping.put(entry.getKey(), outputStream.getWrittenBytesCount());
+                indexTracker = 0;
+            }
+
+            for (Rule rule : entry.getValue()) {
+                bitOutputStream.clear();
+                serializeRule(rule, bitOutputStream);
+                outputStream.write(bitOutputStream.toByteArray());
+                indexTracker++;
+            }
         }
+        indexMapping.put(END_INDEXING_KEY, outputStream.getWrittenBytesCount());
+
+        return indexMapping;
     }
 
     private void serializeRule(Rule rule, BitOutputStream bitOutputStream) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
index f9c7912..cbc365e 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
@@ -38,23 +38,19 @@
     private static final String DEFAULT_RULE_KEY = "N/A";
 
     /**
-     * Splits a given rule list into three indexing categories and returns a sorted list of rules
-     * per each index.
-     *
-     * The sorting guarantees an order based on the key but the rules that have the same key
-     * can be in arbitrary order. For example, given the rules of [package_name_a_rule_1,
-     * package_name_a_rule_2, package_name_b_rule_3, package_name_b_rule_4], the  method will
-     * guarantee that package_name_b rules (i.e., 3 and 4) will never come before package_name_a
-     * rules (i.e., 1 and 2). However, we do not care about the ordering between rule 1 and 2.
-     * We also do not care about the ordering between rule 3 and 4.
+     * Splits a given rule list into three indexing categories. Each rule category is returned as a
+     * TreeMap that is sorted by their indexing keys -- where keys correspond to package name for
+     * PACKAGE_NAME_INDEXED rules, app certificate for APP_CERTIFICATE_INDEXED rules and N/A for
+     * NOT_INDEXED rules.
      */
-    public static Map<Integer, List<Rule>> splitRulesIntoIndexBuckets(List<Rule> rules) {
+    public static Map<Integer, TreeMap<String, List<Rule>>> splitRulesIntoIndexBuckets(
+            List<Rule> rules) {
         if (rules == null) {
             throw new IllegalArgumentException(
                     "Index buckets cannot be created for null rule list.");
         }
 
-        Map<Integer, Map<String, List<Rule>>> typeOrganizedRuleMap = new HashMap();
+        Map<Integer, TreeMap<String, List<Rule>>> typeOrganizedRuleMap = new HashMap();
         typeOrganizedRuleMap.put(NOT_INDEXED, new TreeMap());
         typeOrganizedRuleMap.put(PACKAGE_NAME_INDEXED, new TreeMap());
         typeOrganizedRuleMap.put(APP_CERTIFICATE_INDEXED, new TreeMap());
@@ -87,19 +83,7 @@
                     .add(rule);
         }
 
-        // Per indexing type, create the sorted rule set based on their key.
-        Map<Integer, List<Rule>> orderedListPerIndexingType = new HashMap<>();
-
-        for (Integer indexingKey : typeOrganizedRuleMap.keySet()) {
-            List<Rule> sortedRules = new ArrayList();
-            for (Map.Entry<String, List<Rule>> entry :
-                    typeOrganizedRuleMap.get(indexingKey).entrySet()) {
-                sortedRules.addAll(entry.getValue());
-            }
-            orderedListPerIndexingType.put(indexingKey, sortedRules);
-        }
-
-        return orderedListPerIndexingType;
+        return typeOrganizedRuleMap;
     }
 
     private static RuleIndexingDetails getIndexingDetails(Formula formula) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index ebf6a2e..4c04dbc 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -35,6 +35,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.TreeMap;
 
 /** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
 public class RuleXmlSerializer implements RuleSerializer {
@@ -84,7 +85,7 @@
             throws RuleSerializeException {
         try {
             // Determine the indexing groups and the order of the rules within each indexed group.
-            Map<Integer, List<Rule>> indexedRules =
+            Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
                     RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
 
             // Write the XML formatted rules in order.
@@ -101,10 +102,13 @@
         }
     }
 
-    private void serializeRuleList(List<Rule> rules, XmlSerializer xmlSerializer)
+    private void serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+            XmlSerializer xmlSerializer)
             throws IOException {
-        for (Rule rule : rules) {
-            serializeRule(rule, xmlSerializer);
+        for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
+            for (Rule rule : entry.getValue()) {
+                serializeRule(rule, xmlSerializer);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 423001f..f8d8f9f 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -286,6 +286,11 @@
         if (mActiveConnection != connection) {
             return;
         }
+        if (sessionInfo != null) {
+            sessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+                    .setProviderId(getUniqueId())
+                    .build();
+        }
         mCallback.onSessionCreated(this, sessionInfo, requestId);
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 0bdcc97..82d2250 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1071,12 +1071,6 @@
                 return;
             }
 
-            //TODO: remove this when we are sure that request id is properly implemented.
-            if (matchingRequest.mClientRecord.mClientId != toClientId(requestId)) {
-                Slog.w(TAG, "Client id is changed. This shouldn't happen.");
-                return;
-            }
-
             mSessionCreationRequests.remove(matchingRequest);
 
             if (sessionInfo == null) {
@@ -1086,21 +1080,17 @@
                 return;
             }
 
-            RouteSessionInfo sessionInfoWithProviderId = new RouteSessionInfo.Builder(sessionInfo)
-                    .setProviderId(provider.getUniqueId())
-                    .build();
-
             String originalRouteId = matchingRequest.mRoute.getId();
             String originalCategory = matchingRequest.mControlCategory;
             Client2Record client2Record = matchingRequest.mClientRecord;
 
-            if (!sessionInfoWithProviderId.getSelectedRoutes().contains(originalRouteId)
+            if (!sessionInfo.getSelectedRoutes().contains(originalRouteId)
                     || !TextUtils.equals(originalCategory,
-                        sessionInfoWithProviderId.getControlCategory())) {
+                        sessionInfo.getControlCategory())) {
                 Slog.w(TAG, "Created session doesn't match the original request."
                         + " originalRouteId=" + originalRouteId
                         + ", originalCategory=" + originalCategory + ", requestId=" + requestId
-                        + ", sessionInfo=" + sessionInfoWithProviderId);
+                        + ", sessionInfo=" + sessionInfo);
                 notifySessionCreationFailed(matchingRequest.mClientRecord,
                         toClientRequestId(requestId));
                 return;
@@ -1108,8 +1098,8 @@
 
             // Succeeded
             notifySessionCreated(matchingRequest.mClientRecord,
-                    sessionInfoWithProviderId, toClientRequestId(requestId));
-            mSessionToClientMap.put(sessionInfoWithProviderId.getUniqueSessionId(), client2Record);
+                    sessionInfo, toClientRequestId(requestId));
+            mSessionToClientMap.put(sessionInfo.getUniqueSessionId(), client2Record);
             // TODO: Tell managers for the session creation
         }
 
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 4cb41da..ef8f647 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -45,12 +45,12 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
 import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.Preconditions;
 import com.android.server.ConnectivityService;
 import com.android.server.EventLogTags;
 import com.android.server.connectivity.Vpn;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * State tracker for lockdown mode. Watches for normal {@link NetworkInfo} to be
@@ -90,11 +90,11 @@
             @NonNull Handler handler,
             @NonNull Vpn vpn,
             @NonNull VpnProfile profile) {
-        mContext = Preconditions.checkNotNull(context);
-        mConnService = Preconditions.checkNotNull(connService);
-        mHandler = Preconditions.checkNotNull(handler);
-        mVpn = Preconditions.checkNotNull(vpn);
-        mProfile = Preconditions.checkNotNull(profile);
+        mContext = Objects.requireNonNull(context);
+        mConnService = Objects.requireNonNull(connService);
+        mHandler = Objects.requireNonNull(handler);
+        mVpn = Objects.requireNonNull(vpn);
+        mProfile = Objects.requireNonNull(profile);
 
         final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
         mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 99562eb..0171e1f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -91,7 +91,6 @@
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import static com.android.internal.util.ArrayUtils.appendInt;
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
@@ -614,12 +613,12 @@
     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
             INetworkManagementService networkManagement, IPackageManager pm, Clock clock,
             File systemDir, boolean suppressDefaultPolicy) {
-        mContext = checkNotNull(context, "missing context");
-        mActivityManager = checkNotNull(activityManager, "missing activityManager");
-        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
+        mContext = Objects.requireNonNull(context, "missing context");
+        mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager");
+        mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement");
         mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
                 Context.DEVICE_IDLE_CONTROLLER));
-        mClock = checkNotNull(clock, "missing Clock");
+        mClock = Objects.requireNonNull(clock, "missing Clock");
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
         mIPm = pm;
@@ -646,7 +645,7 @@
     }
 
     public void bindConnectivityManager(IConnectivityManager connManager) {
-        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
+        mConnManager = Objects.requireNonNull(connManager, "missing IConnectivityManager");
     }
 
     @GuardedBy("mUidRulesFirstLock")
@@ -3295,7 +3294,7 @@
         enforceSubscriptionPlanValidity(plans);
 
         for (SubscriptionPlan plan : plans) {
-            Preconditions.checkNotNull(plan);
+            Objects.requireNonNull(plan);
         }
 
         final long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 6af962b..9eff5d1 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -21,8 +21,6 @@
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
 import android.net.NetworkStatsHistory;
@@ -54,6 +52,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Logic to record deltas between periodic {@link NetworkStats} snapshots into
@@ -116,9 +115,9 @@
      */
     public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver<String> observer,
             DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
-        mRotator = checkNotNull(rotator, "missing FileRotator");
-        mObserver = checkNotNull(observer, "missing NonMonotonicObserver");
-        mDropBox = checkNotNull(dropBox, "missing DropBoxManager");
+        mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
+        mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
+        mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
         mCookie = cookie;
 
         mBucketDuration = bucketDuration;
@@ -165,7 +164,7 @@
      * as reference is valid.
      */
     public NetworkStatsCollection getOrLoadCompleteLocked() {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
@@ -175,7 +174,7 @@
     }
 
     public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(start, end);
@@ -280,7 +279,7 @@
      * {@link #mPersistThresholdBytes}.
      */
     public void maybePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         final long pendingBytes = mPending.getTotalBytes();
         if (pendingBytes >= mPersistThresholdBytes) {
             forcePersistLocked(currentTimeMillis);
@@ -293,7 +292,7 @@
      * Force persisting any pending deltas.
      */
     public void forcePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         if (mPending.isDirty()) {
             if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
             try {
@@ -356,7 +355,7 @@
         private final NetworkStatsCollection mCollection;
 
         public CombiningRewriter(NetworkStatsCollection collection) {
-            mCollection = checkNotNull(collection, "missing NetworkStatsCollection");
+            mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
         }
 
         @Override
@@ -418,7 +417,7 @@
     }
 
     public void importLegacyNetworkLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
@@ -438,7 +437,7 @@
     }
 
     public void importLegacyUidLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0288f0c..ec8a8e7 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -65,7 +65,6 @@
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -148,6 +147,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Collect and persist detailed network statistics, and provide this data to
@@ -357,17 +357,18 @@
             TelephonyManager teleManager, NetworkStatsSettings settings,
             NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
             File baseDir) {
-        mContext = checkNotNull(context, "missing Context");
-        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
-        mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
-        mClock = checkNotNull(clock, "missing Clock");
-        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
-        mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
-        mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
-        mStatsFactory = checkNotNull(factory, "missing factory");
-        mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
-        mSystemDir = checkNotNull(systemDir, "missing systemDir");
-        mBaseDir = checkNotNull(baseDir, "missing baseDir");
+        mContext = Objects.requireNonNull(context, "missing Context");
+        mNetworkManager = Objects.requireNonNull(networkManager,
+            "missing INetworkManagementService");
+        mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
+        mClock = Objects.requireNonNull(clock, "missing Clock");
+        mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
+        mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager");
+        mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
+        mStatsFactory = Objects.requireNonNull(factory, "missing factory");
+        mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
+        mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
+        mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
         mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
     }
 
@@ -896,11 +897,11 @@
     @Override
     public DataUsageRequest registerUsageCallback(String callingPackage,
                 DataUsageRequest request, Messenger messenger, IBinder binder) {
-        checkNotNull(callingPackage, "calling package is null");
-        checkNotNull(request, "DataUsageRequest is null");
-        checkNotNull(request.template, "NetworkTemplate is null");
-        checkNotNull(messenger, "messenger is null");
-        checkNotNull(binder, "binder is null");
+        Objects.requireNonNull(callingPackage, "calling package is null");
+        Objects.requireNonNull(request, "DataUsageRequest is null");
+        Objects.requireNonNull(request.template, "NetworkTemplate is null");
+        Objects.requireNonNull(messenger, "messenger is null");
+        Objects.requireNonNull(binder, "binder is null");
 
         int callingUid = Binder.getCallingUid();
         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
@@ -921,7 +922,7 @@
 
     @Override
     public void unregisterUsageRequest(DataUsageRequest request) {
-        checkNotNull(request, "DataUsageRequest is null");
+        Objects.requireNonNull(request, "DataUsageRequest is null");
 
         int callingUid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
@@ -1795,7 +1796,7 @@
         private final ContentResolver mResolver;
 
         public DefaultNetworkStatsSettings(Context context) {
-            mResolver = checkNotNull(context.getContentResolver());
+            mResolver = Objects.requireNonNull(context.getContentResolver());
             // TODO: adjust these timings for production builds
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 12afef2..f42f4f7 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2261,8 +2261,8 @@
 
     private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
             boolean fromApp, boolean fromListener) {
-        Preconditions.checkNotNull(group);
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(group);
+        Objects.requireNonNull(pkg);
 
         final NotificationChannelGroup preUpdate =
                 mPreferencesHelper.getNotificationChannelGroup(group.getId(), pkg, uid);
@@ -3005,7 +3005,7 @@
             boolean needsPolicyFileChange = false;
             for (int i = 0; i < channelsSize; i++) {
                 final NotificationChannel channel = channels.get(i);
-                Preconditions.checkNotNull(channel, "channel in list is null");
+                Objects.requireNonNull(channel, "channel in list is null");
                 needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid,
                         channel, true /* fromTargetApp */,
                         mConditionProviders.isPackageOrComponentAllowed(
@@ -3126,7 +3126,7 @@
         public void updateNotificationChannelForPackage(String pkg, int uid,
                 NotificationChannel channel) {
             enforceSystemOrSystemUI("Caller not system or systemui");
-            Preconditions.checkNotNull(channel);
+            Objects.requireNonNull(channel);
             updateNotificationChannelInt(pkg, uid, channel, false);
         }
 
@@ -3877,21 +3877,21 @@
 
         @Override
         public AutomaticZenRule getAutomaticZenRule(String id) throws RemoteException {
-            Preconditions.checkNotNull(id, "Id is null");
+            Objects.requireNonNull(id, "Id is null");
             enforcePolicyAccess(Binder.getCallingUid(), "getAutomaticZenRule");
             return mZenModeHelper.getAutomaticZenRule(id);
         }
 
         @Override
         public String addAutomaticZenRule(AutomaticZenRule automaticZenRule) {
-            Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
-            Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+            Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+            Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
             if (automaticZenRule.getOwner() == null
                     && automaticZenRule.getConfigurationActivity() == null) {
                 throw new NullPointerException(
                         "Rule must have a conditionproviderservice and/or configuration activity");
             }
-            Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+            Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
             if (automaticZenRule.getZenPolicy() != null
                     && automaticZenRule.getInterruptionFilter() != INTERRUPTION_FILTER_PRIORITY) {
                 throw new IllegalArgumentException("ZenPolicy is only applicable to "
@@ -3906,14 +3906,14 @@
         @Override
         public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule)
                 throws RemoteException {
-            Preconditions.checkNotNull(automaticZenRule, "automaticZenRule is null");
-            Preconditions.checkNotNull(automaticZenRule.getName(), "Name is null");
+            Objects.requireNonNull(automaticZenRule, "automaticZenRule is null");
+            Objects.requireNonNull(automaticZenRule.getName(), "Name is null");
             if (automaticZenRule.getOwner() == null
                     && automaticZenRule.getConfigurationActivity() == null) {
                 throw new NullPointerException(
                         "Rule must have a conditionproviderservice and/or configuration activity");
             }
-            Preconditions.checkNotNull(automaticZenRule.getConditionId(), "ConditionId is null");
+            Objects.requireNonNull(automaticZenRule.getConditionId(), "ConditionId is null");
             enforcePolicyAccess(Binder.getCallingUid(), "updateAutomaticZenRule");
 
             return mZenModeHelper.updateAutomaticZenRule(id, automaticZenRule,
@@ -3922,7 +3922,7 @@
 
         @Override
         public boolean removeAutomaticZenRule(String id) throws RemoteException {
-            Preconditions.checkNotNull(id, "Id is null");
+            Objects.requireNonNull(id, "Id is null");
             // Verify that they can modify zen rules.
             enforcePolicyAccess(Binder.getCallingUid(), "removeAutomaticZenRule");
 
@@ -3931,7 +3931,7 @@
 
         @Override
         public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
-            Preconditions.checkNotNull(packageName, "Package name is null");
+            Objects.requireNonNull(packageName, "Package name is null");
             enforceSystemOrSystemUI("removeAutomaticZenRules");
 
             return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
@@ -3939,7 +3939,7 @@
 
         @Override
         public int getRuleInstanceCount(ComponentName owner) throws RemoteException {
-            Preconditions.checkNotNull(owner, "Owner is null");
+            Objects.requireNonNull(owner, "Owner is null");
             enforceSystemOrSystemUI("getRuleInstanceCount");
 
             return mZenModeHelper.getCurrentInstanceCount(owner);
@@ -3947,8 +3947,8 @@
 
         @Override
         public void setAutomaticZenRuleState(String id, Condition condition) {
-            Preconditions.checkNotNull(id, "id is null");
-            Preconditions.checkNotNull(condition, "Condition is null");
+            Objects.requireNonNull(id, "id is null");
+            Objects.requireNonNull(condition, "Condition is null");
 
             enforcePolicyAccess(Binder.getCallingUid(), "setAutomaticZenRuleState");
 
@@ -4292,7 +4292,7 @@
 
         @Override
         public boolean isNotificationListenerAccessGranted(ComponentName listener) {
-            Preconditions.checkNotNull(listener);
+            Objects.requireNonNull(listener);
             checkCallerIsSystemOrSameApp(listener.getPackageName());
             return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
                     getCallingUserHandle().getIdentifier());
@@ -4301,7 +4301,7 @@
         @Override
         public boolean isNotificationListenerAccessGrantedForUser(ComponentName listener,
                 int userId) {
-            Preconditions.checkNotNull(listener);
+            Objects.requireNonNull(listener);
             checkCallerIsSystem();
             return mListeners.isPackageOrComponentAllowed(listener.flattenToString(),
                     userId);
@@ -4309,7 +4309,7 @@
 
         @Override
         public boolean isNotificationAssistantAccessGranted(ComponentName assistant) {
-            Preconditions.checkNotNull(assistant);
+            Objects.requireNonNull(assistant);
             checkCallerIsSystemOrSameApp(assistant.getPackageName());
             return mAssistants.isPackageOrComponentAllowed(assistant.flattenToString(),
                     getCallingUserHandle().getIdentifier());
@@ -4332,7 +4332,7 @@
         @Override
         public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
                 boolean granted) {
-            Preconditions.checkNotNull(listener);
+            Objects.requireNonNull(listener);
             checkCallerIsSystemOrShell();
             final long identity = Binder.clearCallingIdentity();
             try {
@@ -4450,7 +4450,7 @@
         public void updateNotificationChannelGroupFromPrivilegedListener(
                 INotificationListener token, String pkg, UserHandle user,
                 NotificationChannelGroup group) throws RemoteException {
-            Preconditions.checkNotNull(user);
+            Objects.requireNonNull(user);
             verifyPrivilegedListener(token, user, false);
             createNotificationChannelGroup(
                     pkg, getUidForPackageAndUser(pkg, user), group, false, true);
@@ -4460,9 +4460,9 @@
         @Override
         public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
                 String pkg, UserHandle user, NotificationChannel channel) throws RemoteException {
-            Preconditions.checkNotNull(channel);
-            Preconditions.checkNotNull(pkg);
-            Preconditions.checkNotNull(user);
+            Objects.requireNonNull(channel);
+            Objects.requireNonNull(pkg);
+            Objects.requireNonNull(user);
 
             verifyPrivilegedListener(token, user, false);
             updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
@@ -4471,8 +4471,8 @@
         @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
                 INotificationListener token, String pkg, UserHandle user) throws RemoteException {
-            Preconditions.checkNotNull(pkg);
-            Preconditions.checkNotNull(user);
+            Objects.requireNonNull(pkg);
+            Objects.requireNonNull(user);
             verifyPrivilegedListener(token, user, true);
 
             return mPreferencesHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
@@ -4483,8 +4483,8 @@
         public ParceledListSlice<NotificationChannelGroup>
                 getNotificationChannelGroupsFromPrivilegedListener(
                 INotificationListener token, String pkg, UserHandle user) throws RemoteException {
-            Preconditions.checkNotNull(pkg);
-            Preconditions.checkNotNull(user);
+            Objects.requireNonNull(pkg);
+            Objects.requireNonNull(user);
             verifyPrivilegedListener(token, user, true);
 
             List<NotificationChannelGroup> groups = new ArrayList<>();
@@ -4520,7 +4520,7 @@
 
         @Override
         public boolean isPackagePaused(String pkg) {
-            Preconditions.checkNotNull(pkg);
+            Objects.requireNonNull(pkg);
             checkCallerIsSameApp(pkg);
 
             return isPackagePausedOrSuspended(pkg, Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index b1ffa8c..cdb0a17 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -621,10 +621,10 @@
     @Override
     public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
             boolean fromTargetApp) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(group);
-        Preconditions.checkNotNull(group.getId());
-        Preconditions.checkNotNull(!TextUtils.isEmpty(group.getName()));
+        Objects.requireNonNull(pkg);
+        Objects.requireNonNull(group);
+        Objects.requireNonNull(group.getId());
+        Objects.requireNonNull(!TextUtils.isEmpty(group.getName()));
         synchronized (mPackagePreferences) {
             PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -658,9 +658,9 @@
     @Override
     public boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel,
             boolean fromTargetApp, boolean hasDndAccess) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(channel);
-        Preconditions.checkNotNull(channel.getId());
+        Objects.requireNonNull(pkg);
+        Objects.requireNonNull(channel);
+        Objects.requireNonNull(channel.getId());
         Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
         boolean needsPolicyFileChange = false;
         synchronized (mPackagePreferences) {
@@ -788,8 +788,8 @@
     @Override
     public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
             boolean fromUser) {
-        Preconditions.checkNotNull(updatedChannel);
-        Preconditions.checkNotNull(updatedChannel.getId());
+        Objects.requireNonNull(updatedChannel);
+        Objects.requireNonNull(updatedChannel.getId());
         synchronized (mPackagePreferences) {
             PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -850,7 +850,7 @@
     @Override
     public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
             boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         synchronized (mPackagePreferences) {
             PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -891,8 +891,8 @@
     @Override
     @VisibleForTesting
     public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
-        Preconditions.checkNotNull(pkg);
-        Preconditions.checkNotNull(channelId);
+        Objects.requireNonNull(pkg);
+        Objects.requireNonNull(channelId);
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -904,7 +904,7 @@
 
     @Override
     public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -993,7 +993,7 @@
 
     public NotificationChannelGroup getNotificationChannelGroupWithChannels(String pkg,
             int uid, String groupId, boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
             if (r == null || groupId == null || !r.groups.containsKey(groupId)) {
@@ -1016,7 +1016,7 @@
 
     public NotificationChannelGroup getNotificationChannelGroup(String groupId, String pkg,
             int uid) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
             if (r == null) {
@@ -1029,7 +1029,7 @@
     @Override
     public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
             int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         Map<String, NotificationChannelGroup> groups = new ArrayMap<>();
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1111,7 +1111,7 @@
     @Override
     public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
             boolean includeDeleted) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         List<NotificationChannel> channels = new ArrayList<>();
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1168,7 +1168,7 @@
     }
 
     public int getDeletedChannelCount(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         int deletedCount = 0;
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
@@ -1187,7 +1187,7 @@
     }
 
     public int getBlockedChannelCount(String pkg, int uid) {
-        Preconditions.checkNotNull(pkg);
+        Objects.requireNonNull(pkg);
         int blockedCount = 0;
         synchronized (mPackagePreferences) {
             PackagePreferences r = getPackagePreferencesLocked(pkg, uid);
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 9a1b30d..1e2d52d 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -38,6 +38,7 @@
 import com.android.server.SystemConfig;
 
 import java.io.FileDescriptor;
+import java.util.Objects;
 
 /**
  * Implementation of the service that provides a privileged API to capture and consume bugreports.
@@ -67,9 +68,9 @@
             FileDescriptor bugreportFd, FileDescriptor screenshotFd,
             int bugreportMode, IDumpstateListener listener) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
-        Preconditions.checkNotNull(callingPackage);
-        Preconditions.checkNotNull(bugreportFd);
-        Preconditions.checkNotNull(listener);
+        Objects.requireNonNull(callingPackage);
+        Objects.requireNonNull(bugreportFd);
+        Objects.requireNonNull(listener);
         validateBugreportMode(bugreportMode);
         final long identity = Binder.clearCallingIdentity();
         try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 785ca7d..b793d6d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12872,7 +12872,7 @@
 
     @Override
     public String[] getUnsuspendablePackagesForUser(String[] packageNames, int userId) {
-        Preconditions.checkNotNull("packageNames cannot be null", packageNames);
+        Preconditions.checkNotNull(packageNames, "packageNames cannot be null");
         mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
                 "getUnsuspendablePackagesForUser");
         final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c4522e0..392792d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -511,7 +511,7 @@
 
             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
-            Preconditions.checkNotNull(callback, "callback cannot be null");
+            Objects.requireNonNull(callback, "callback cannot be null");
 
             getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags,
                     callback);
@@ -531,7 +531,7 @@
 
             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
-            Preconditions.checkNotNull(callback, "callback cannot be null");
+            Objects.requireNonNull(callback, "callback cannot be null");
 
             getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
                     callback);
@@ -550,7 +550,7 @@
                     "clearRoleHoldersAsUser");
 
             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
-            Preconditions.checkNotNull(callback, "callback cannot be null");
+            Objects.requireNonNull(callback, "callback cannot be null");
 
             getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
         }
@@ -566,7 +566,7 @@
             getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
                     "addOnRoleHoldersChangedListenerAsUser");
 
-            Preconditions.checkNotNull(listener, "listener cannot be null");
+            Objects.requireNonNull(listener, "listener cannot be null");
 
             RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
                     userId);
@@ -584,7 +584,7 @@
             getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
                     "removeOnRoleHoldersChangedListenerAsUser");
 
-            Preconditions.checkNotNull(listener, "listener cannot be null");
+            Objects.requireNonNull(listener, "listener cannot be null");
 
             RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
             if (listener == null) {
@@ -599,7 +599,7 @@
                     RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
                     "setRoleNamesFromController");
 
-            Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
+            Objects.requireNonNull(roleNames, "roleNames cannot be null");
 
             int userId = UserHandle.getCallingUserId();
             getOrCreateUserState(userId).setRoleNames(roleNames);
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index 1123f70..e6e6e23 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.server.rollback;
 
+import android.content.pm.PackageManager;
 import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.PackageRollbackInfo.RestoreInfo;
 import android.os.storage.StorageManager;
@@ -119,11 +120,22 @@
         }
 
         try {
-            mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo,
-                    userId, rollbackId, storageFlags);
+            switch (packageRollbackInfo.getRollbackDataPolicy()) {
+                case PackageManager.RollbackDataPolicy.WIPE:
+                    mInstaller.clearAppData(null, packageRollbackInfo.getPackageName(),
+                            userId, storageFlags, 0);
+                    break;
+                case PackageManager.RollbackDataPolicy.RESTORE:
+                    mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId,
+                            seInfo, userId, rollbackId, storageFlags);
+                    break;
+                default:
+                    break;
+            }
         } catch (InstallerException ie) {
-            Slog.e(TAG, "Unable to restore app data snapshot: "
-                        + packageRollbackInfo.getPackageName(), ie);
+            Slog.e(TAG, "Unable to restore/wipe app data: "
+                    + packageRollbackInfo.getPackageName() + " policy="
+                    + packageRollbackInfo.getRollbackDataPolicy(), ie);
         }
 
         return changedRollback;
@@ -207,13 +219,24 @@
 
             if (hasPendingRestore) {
                 try {
-                    mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
-                            ri.seInfo, userId, rollback.info.getRollbackId(),
-                            Installer.FLAG_STORAGE_CE);
+                    switch (info.getRollbackDataPolicy()) {
+                        case PackageManager.RollbackDataPolicy.WIPE:
+                            mInstaller.clearAppData(null, info.getPackageName(), userId,
+                                    Installer.FLAG_STORAGE_CE, 0);
+                            break;
+                        case PackageManager.RollbackDataPolicy.RESTORE:
+                            mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
+                                    ri.seInfo, userId, rollback.info.getRollbackId(),
+                                    Installer.FLAG_STORAGE_CE);
+                            break;
+                        default:
+                            break;
+                    }
                     info.removeRestoreInfo(ri);
                 } catch (InstallerException ie) {
-                    Slog.e(TAG, "Unable to restore app data snapshot for: "
-                            + info.getPackageName(), ie);
+                    Slog.e(TAG, "Unable to restore/wipe app data for: "
+                            + info.getPackageName() + " policy="
+                            + info.getRollbackDataPolicy(), ie);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 6898e1c..88c1564 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -306,7 +306,7 @@
      * @return boolean True if the rollback was enabled successfully for the specified package.
      */
     boolean enableForPackage(String packageName, long newVersion, long installedVersion,
-            boolean isApex, String sourceDir, String[] splitSourceDirs) {
+            boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) {
         try {
             RollbackStore.backupPackageCodePath(this, packageName, sourceDir);
             if (!ArrayUtils.isEmpty(splitSourceDirs)) {
@@ -323,7 +323,8 @@
                 new VersionedPackage(packageName, newVersion),
                 new VersionedPackage(packageName, installedVersion),
                 new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
-                isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */);
+                isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */,
+                rollbackDataPolicy);
 
         synchronized (mLock) {
             info.getPackages().add(packageRollbackInfo);
@@ -344,10 +345,12 @@
 
             for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
                 if (pkgRollbackInfo.getPackageName().equals(packageName)) {
-                    dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
-
-                    RollbackStore.saveRollback(this);
-                    pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+                    if (pkgRollbackInfo.getRollbackDataPolicy()
+                            == PackageManager.RollbackDataPolicy.RESTORE) {
+                        dataHelper.snapshotAppData(info.getRollbackId(), pkgRollbackInfo, userIds);
+                        pkgRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
+                        RollbackStore.saveRollback(this);
+                    }
                     break;
                 }
             }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 6cdfcff..9a65ae6 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -841,7 +841,7 @@
         ApplicationInfo appInfo = pkgInfo.applicationInfo;
         return rollback.enableForPackage(packageName, newPackage.versionCode,
                 pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir,
-                appInfo.splitSourceDirs);
+                appInfo.splitSourceDirs, session.rollbackDataPolicy);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index bb09584..162a695 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -120,9 +120,7 @@
 
         RollbackInfo rollback = getAvailableRollback(failedPackage);
         if (rollback == null) {
-            Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
-                    + failedPackage.getPackageName() + "] with versionCode: ["
-                    + failedPackage.getVersionCode() + "]");
+            Slog.w(TAG, "Expected rollback but no valid rollback found for " + failedPackage);
             return false;
         }
         rollbackPackage(rollback, failedPackage, rollbackReason);
@@ -212,11 +210,7 @@
         RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
         for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
             for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
-                boolean hasFailedPackage = packageRollback.getPackageName().equals(
-                        failedPackage.getPackageName())
-                        && packageRollback.getVersionRolledBackFrom().getVersionCode()
-                        == failedPackage.getVersionCode();
-                if (hasFailedPackage) {
+                if (packageRollback.getVersionRolledBackFrom().equals(failedPackage)) {
                     return rollback;
                 }
             }
@@ -361,15 +355,6 @@
         }
     }
 
-    private VersionedPackage getVersionedPackage(String packageName) {
-        try {
-            return new VersionedPackage(packageName, mContext.getPackageManager().getPackageInfo(
-                    packageName, 0 /* flags */).getLongVersionCode());
-        } catch (PackageManager.NameNotFoundException e) {
-            return null;
-        }
-    }
-
     /**
      * Rolls back the session that owns {@code failedPackage}
      *
@@ -432,14 +417,8 @@
         List<RollbackInfo> rollbacks = rollbackManager.getAvailableRollbacks();
 
         for (RollbackInfo rollback : rollbacks) {
-            String samplePackageName = rollback.getPackages().get(0).getPackageName();
-            VersionedPackage sampleVersionedPackage = getVersionedPackage(samplePackageName);
-            if (sampleVersionedPackage == null) {
-                Slog.e(TAG, "Failed to rollback " + samplePackageName);
-                continue;
-            }
-            rollbackPackage(rollback, sampleVersionedPackage,
-                    PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+            VersionedPackage sample = rollback.getPackages().get(0).getVersionRolledBackFrom();
+            rollbackPackage(rollback, sample, PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
         }
     }
 
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 550c754..df75a29 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -21,6 +21,7 @@
 import static com.android.server.rollback.Rollback.rollbackStateFromString;
 
 import android.annotation.NonNull;
+import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.content.rollback.PackageRollbackInfo;
 import android.content.rollback.PackageRollbackInfo.RestoreInfo;
@@ -345,6 +346,8 @@
         json.put("installedUsers", convertToJsonArray(snapshottedUsers));
         json.put("ceSnapshotInodes", ceSnapshotInodesToJson(info.getCeSnapshotInodes()));
 
+        json.put("rollbackDataPolicy", info.getRollbackDataPolicy());
+
         return json;
     }
 
@@ -367,8 +370,13 @@
         final SparseLongArray ceSnapshotInodes = ceSnapshotInodesFromJson(
                 json.getJSONArray("ceSnapshotInodes"));
 
+        // Backward compatibility: no such field for old versions.
+        final int rollbackDataPolicy = json.optInt("rollbackDataPolicy",
+                PackageManager.RollbackDataPolicy.RESTORE);
+
         return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
-                pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes);
+                pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes,
+                rollbackDataPolicy);
     }
 
     private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
index 0bbb179..e90c02a 100644
--- a/services/core/java/com/android/server/security/FileIntegrityService.java
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -59,7 +59,7 @@
         }
 
         @Override
-        public boolean isAppSourceCertificateTrusted(byte[] certificateBytes) {
+        public boolean isAppSourceCertificateTrusted(@Nullable byte[] certificateBytes) {
             enforceAnyCallingPermissions(
                     android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
                     android.Manifest.permission.INSTALL_PACKAGES);
@@ -67,7 +67,10 @@
                 if (!isApkVeritySupported()) {
                     return false;
                 }
-
+                if (certificateBytes == null) {
+                    Slog.w(TAG, "Received a null certificate");
+                    return false;
+                }
                 return mTrustedCertificates.contains(toCertificate(certificateBytes));
             } catch (CertificateException e) {
                 Slog.e(TAG, "Failed to convert the certificate: " + e);
@@ -122,7 +125,12 @@
             }
 
             for (File cert : files) {
-                collectCertificate(Files.readAllBytes(cert.toPath()));
+                byte[] certificateBytes = Files.readAllBytes(cert.toPath());
+                if (certificateBytes == null) {
+                    Slog.w(TAG, "The certificate file is empty, ignoring " + cert);
+                    continue;
+                }
+                collectCertificate(certificateBytes);
             }
         } catch (IOException e) {
             Slog.wtf(TAG, "Failed to load fs-verity certificate from " + path, e);
@@ -146,10 +154,10 @@
      * Tries to convert {@code bytes} into an X.509 certificate and store in memory.
      * Errors need to be surpressed in order fo the next certificates to still be collected.
      */
-    private void collectCertificate(@Nullable byte[] bytes) {
+    private void collectCertificate(@NonNull byte[] bytes) {
         try {
             mTrustedCertificates.add(toCertificate(bytes));
-        } catch (CertificateException | AssertionError e) {
+        } catch (CertificateException e) {
             Slog.e(TAG, "Invalid certificate, ignored: " + e);
         }
     }
@@ -159,7 +167,7 @@
      * the rest. The rational is to make it harder to smuggle.
      */
     @NonNull
-    private static X509Certificate toCertificate(@Nullable byte[] bytes)
+    private static X509Certificate toCertificate(@NonNull byte[] bytes)
             throws CertificateException {
         Certificate certificate = sCertFactory.generateCertificate(new ByteArrayInputStream(bytes));
         if (!(certificate instanceof X509Certificate)) {
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 3b2f324..7c8c494 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -106,7 +106,7 @@
     @VisibleForTesting
     SliceManagerService(Context context, Looper looper) {
         mContext = context;
-        mPackageManagerInternal = Preconditions.checkNotNull(
+        mPackageManagerInternal = Objects.requireNonNull(
                 LocalServices.getService(PackageManagerInternal.class));
         mAppOps = context.getSystemService(AppOpsManager.class);
         mAssistUtils = new AssistUtils(context);
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
index a7cfe10..987c05f 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareService.java
@@ -42,6 +42,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -179,8 +180,8 @@
         // Permission check.
         checkPermissions();
         // Input validation.
-        Preconditions.checkNotNull(callback);
-        Preconditions.checkNotNull(callback.asBinder());
+        Objects.requireNonNull(callback);
+        Objects.requireNonNull(callback.asBinder());
 
         synchronized (this) {
             // State validation.
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
index 4898e6b..43047d1 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/ValidationUtil.java
@@ -29,6 +29,7 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -42,7 +43,7 @@
  */
 public class ValidationUtil {
     static void validateUuid(@Nullable String uuid) {
-        Preconditions.checkNotNull(uuid);
+        Objects.requireNonNull(uuid);
         Matcher matcher = UuidUtil.PATTERN.matcher(uuid);
         if (!matcher.matches()) {
             throw new IllegalArgumentException(
@@ -55,37 +56,37 @@
     }
 
     static void validateModel(@Nullable SoundModel model, int expectedType) {
-        Preconditions.checkNotNull(model);
+        Objects.requireNonNull(model);
         if (model.type != expectedType) {
             throw new IllegalArgumentException("Invalid type");
         }
         validateUuid(model.uuid);
         validateUuid(model.vendorUuid);
-        Preconditions.checkNotNull(model.data);
+        Objects.requireNonNull(model.data);
     }
 
     static void validatePhraseModel(@Nullable PhraseSoundModel model) {
-        Preconditions.checkNotNull(model);
+        Objects.requireNonNull(model);
         validateModel(model.common, SoundModelType.KEYPHRASE);
-        Preconditions.checkNotNull(model.phrases);
+        Objects.requireNonNull(model.phrases);
         for (Phrase phrase : model.phrases) {
-            Preconditions.checkNotNull(phrase);
+            Objects.requireNonNull(phrase);
             if ((phrase.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
                     | RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
                     | RecognitionMode.GENERIC_TRIGGER)) != 0) {
                 throw new IllegalArgumentException("Invalid recognitionModes");
             }
-            Preconditions.checkNotNull(phrase.users);
-            Preconditions.checkNotNull(phrase.locale);
-            Preconditions.checkNotNull(phrase.text);
+            Objects.requireNonNull(phrase.users);
+            Objects.requireNonNull(phrase.locale);
+            Objects.requireNonNull(phrase.text);
         }
     }
 
     static void validateRecognitionConfig(@Nullable RecognitionConfig config) {
-        Preconditions.checkNotNull(config);
-        Preconditions.checkNotNull(config.phraseRecognitionExtras);
+        Objects.requireNonNull(config);
+        Objects.requireNonNull(config.phraseRecognitionExtras);
         for (PhraseRecognitionExtra extra : config.phraseRecognitionExtras) {
-            Preconditions.checkNotNull(extra);
+            Objects.requireNonNull(extra);
             if ((extra.recognitionModes & ~(RecognitionMode.VOICE_TRIGGER
                     | RecognitionMode.USER_IDENTIFICATION | RecognitionMode.USER_AUTHENTICATION
                     | RecognitionMode.GENERIC_TRIGGER)) != 0) {
@@ -94,15 +95,15 @@
             if (extra.confidenceLevel < 0 || extra.confidenceLevel > 100) {
                 throw new IllegalArgumentException("Invalid confidenceLevel");
             }
-            Preconditions.checkNotNull(extra.levels);
+            Objects.requireNonNull(extra.levels);
             for (ConfidenceLevel level : extra.levels) {
-                Preconditions.checkNotNull(level);
+                Objects.requireNonNull(level);
                 if (level.levelPercent < 0 || level.levelPercent > 100) {
                     throw new IllegalArgumentException("Invalid confidenceLevel");
                 }
             }
         }
-        Preconditions.checkNotNull(config.data);
+        Objects.requireNonNull(config.data);
     }
 
     static void validateModelParameter(int modelParam) {
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index 0b51f9c..ecbc88f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -59,7 +59,7 @@
      * @param volume Volume to check for apps.
      */
     public AppCollector(Context context, @NonNull VolumeInfo volume) {
-        Preconditions.checkNotNull(volume);
+        Objects.requireNonNull(volume);
 
         mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
                 volume,
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 60de10c..aafadf9 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -66,6 +66,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * CacheQuotaStrategy is a strategy for determining cache quotas using usage stats and foreground
@@ -95,10 +96,10 @@
     public CacheQuotaStrategy(
             Context context, UsageStatsManagerInternal usageStatsManager, Installer installer,
             ArrayMap<String, SparseLongArray> quotaMap) {
-        mContext = Preconditions.checkNotNull(context);
-        mUsageStats = Preconditions.checkNotNull(usageStatsManager);
-        mInstaller = Preconditions.checkNotNull(installer);
-        mQuotaMap = Preconditions.checkNotNull(quotaMap);
+        mContext = Objects.requireNonNull(context);
+        mUsageStats = Objects.requireNonNull(usageStatsManager);
+        mInstaller = Objects.requireNonNull(installer);
+        mQuotaMap = Objects.requireNonNull(quotaMap);
         mPreviousValuesFile = new AtomicFile(new File(
                 new File(Environment.getDataDirectory(), "system"), "cachequota.xml"));
     }
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index aa3ab63..f4fb93a 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -43,6 +43,7 @@
 import com.android.internal.util.Preconditions;
 
 import java.io.FileDescriptor;
+import java.util.Objects;
 
 /**
  * Controls storage sessions for users initiated by the {@link StorageManagerService}.
@@ -63,7 +64,7 @@
     private volatile boolean mIsResetting;
 
     public StorageSessionController(Context context, boolean isFuseEnabled) {
-        mContext = Preconditions.checkNotNull(context);
+        mContext = Objects.requireNonNull(context);
         mIsFuseEnabled = isFuseEnabled;
     }
 
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 10514ad..c02ded8 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -48,6 +48,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -69,7 +70,7 @@
     @GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
 
     public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
-        mContext = Preconditions.checkNotNull(context);
+        mContext = Objects.requireNonNull(context);
         mUserId = Preconditions.checkArgumentNonnegative(userId);
         mSessionController = controller;
     }
@@ -83,10 +84,10 @@
      */
     public void startSession(String sessionId, ParcelFileDescriptor pfd, String upperPath,
             String lowerPath) throws ExternalStorageServiceException {
-        Preconditions.checkNotNull(sessionId);
-        Preconditions.checkNotNull(pfd);
-        Preconditions.checkNotNull(upperPath);
-        Preconditions.checkNotNull(lowerPath);
+        Objects.requireNonNull(sessionId);
+        Objects.requireNonNull(pfd);
+        Objects.requireNonNull(upperPath);
+        Objects.requireNonNull(lowerPath);
 
         prepareRemote();
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 6a986b9..5283cc4 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -62,6 +62,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayDeque;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Queue;
 
 /**
@@ -137,7 +138,7 @@
     private TextClassificationConstants mSettings;
 
     private TextClassificationManagerService(Context context) {
-        mContext = Preconditions.checkNotNull(context);
+        mContext = Objects.requireNonNull(context);
         mLock = new Object();
         mSettingsListener = new TextClassifierSettingsListener(mContext);
     }
@@ -156,8 +157,8 @@
             @Nullable TextClassificationSessionId sessionId,
             TextSelection.Request request, ITextClassifierCallback callback)
             throws RemoteException {
-        Preconditions.checkNotNull(request);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(request);
+        Objects.requireNonNull(callback);
         final int userId = request.getUserId();
         validateInput(mContext, request.getCallingPackageName(), userId);
 
@@ -186,8 +187,8 @@
             @Nullable TextClassificationSessionId sessionId,
             TextClassification.Request request, ITextClassifierCallback callback)
             throws RemoteException {
-        Preconditions.checkNotNull(request);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(request);
+        Objects.requireNonNull(callback);
         final int userId = request.getUserId();
         validateInput(mContext, request.getCallingPackageName(), userId);
 
@@ -215,8 +216,8 @@
             @Nullable TextClassificationSessionId sessionId,
             TextLinks.Request request, ITextClassifierCallback callback)
             throws RemoteException {
-        Preconditions.checkNotNull(request);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(request);
+        Objects.requireNonNull(callback);
         final int userId = request.getUserId();
         validateInput(mContext, request.getCallingPackageName(), userId);
 
@@ -244,7 +245,7 @@
     public void onSelectionEvent(
             @Nullable TextClassificationSessionId sessionId, SelectionEvent event)
             throws RemoteException {
-        Preconditions.checkNotNull(event);
+        Objects.requireNonNull(event);
         final int userId = event.getUserId();
         validateInput(mContext, event.getPackageName(), userId);
 
@@ -268,7 +269,7 @@
     public void onTextClassifierEvent(
             @Nullable TextClassificationSessionId sessionId,
             TextClassifierEvent event) throws RemoteException {
-        Preconditions.checkNotNull(event);
+        Objects.requireNonNull(event);
         final String packageName = event.getEventContext() == null
                 ? null
                 : event.getEventContext().getPackageName();
@@ -299,8 +300,8 @@
             @Nullable TextClassificationSessionId sessionId,
             TextLanguage.Request request,
             ITextClassifierCallback callback) throws RemoteException {
-        Preconditions.checkNotNull(request);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(request);
+        Objects.requireNonNull(callback);
         final int userId = request.getUserId();
         validateInput(mContext, request.getCallingPackageName(), userId);
 
@@ -329,8 +330,8 @@
             @Nullable TextClassificationSessionId sessionId,
             ConversationActions.Request request,
             ITextClassifierCallback callback) throws RemoteException {
-        Preconditions.checkNotNull(request);
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(request);
+        Objects.requireNonNull(callback);
         final int userId = request.getUserId();
         validateInput(mContext, request.getCallingPackageName(), userId);
 
@@ -360,8 +361,8 @@
     public void onCreateTextClassificationSession(
             TextClassificationContext classificationContext, TextClassificationSessionId sessionId)
             throws RemoteException {
-        Preconditions.checkNotNull(sessionId);
-        Preconditions.checkNotNull(classificationContext);
+        Objects.requireNonNull(sessionId);
+        Objects.requireNonNull(classificationContext);
         final int userId = classificationContext.getUserId();
         validateInput(mContext, classificationContext.getPackageName(), userId);
 
@@ -391,7 +392,7 @@
     @Override
     public void onDestroyTextClassificationSession(TextClassificationSessionId sessionId)
             throws RemoteException {
-        Preconditions.checkNotNull(sessionId);
+        Objects.requireNonNull(sessionId);
 
         synchronized (mLock) {
             final int userId = mSessionUserIds.containsKey(sessionId)
@@ -514,7 +515,7 @@
                 UserState owningUser, int uid) {
             mName = name;
             mRequest =
-                    logOnFailure(Preconditions.checkNotNull(request), "handling pending request");
+                    logOnFailure(Objects.requireNonNull(request), "handling pending request");
             mOnServiceFailure =
                     logOnFailure(onServiceFailure, "notifying callback of service failure");
             mBinder = binder;
@@ -604,8 +605,8 @@
 
         private UserState(int userId, Context context, Object lock) {
             mUserId = userId;
-            mContext = Preconditions.checkNotNull(context);
-            mLock = Preconditions.checkNotNull(lock);
+            mContext = Objects.requireNonNull(context);
+            mLock = Objects.requireNonNull(lock);
         }
 
         @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 04839e1..e3b7c0a 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -103,6 +103,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 
 /** Manages uri grants. */
 public class UriGrantsManagerService extends IUriGrantsManager.Stub {
@@ -215,7 +216,7 @@
     public ParceledListSlice<android.content.UriPermission> getUriPermissions(
             String packageName, boolean incoming, boolean persistedOnly) {
         enforceNotIsolatedCaller("getUriPermissions");
-        Preconditions.checkNotNull(packageName, "packageName");
+        Objects.requireNonNull(packageName, "packageName");
 
         final int callingUid = Binder.getCallingUid();
         final int callingUserId = UserHandle.getUserId(callingUid);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 255ef6e..a26dfdb 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -276,7 +276,6 @@
                     display.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.token = mServerChannel.getToken();
-            mDragWindowHandle.layer = getDragLayerLocked();
             mDragWindowHandle.layoutParamsFlags = 0;
             mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
             mDragWindowHandle.dispatchingTimeoutNanos =
@@ -345,12 +344,6 @@
         }
     }
 
-    int getDragLayerLocked() {
-        return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
-                * WindowManagerService.TYPE_LAYER_MULTIPLIER
-                + WindowManagerService.TYPE_LAYER_OFFSET;
-    }
-
     /* call out to each visible window/session informing it about the drag
      */
     void broadcastDragStartedLocked(final float touchX, final float touchY) {
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index ebe9f08..c6183de 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -76,7 +76,6 @@
         mWindowHandle.name = name;
         mWindowHandle.token = mServerChannel.getToken();
         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
-        mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
         mWindowHandle.layoutParamsFlags = 0;
         mWindowHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
@@ -150,12 +149,6 @@
         t.setLayer(mInputSurface, layer);
     }
 
-    private int getLayerLw(int windowType) {
-        return mService.mPolicy.getWindowLayerFromTypeLw(windowType)
-                * WindowManagerService.TYPE_LAYER_MULTIPLIER
-                + WindowManagerService.TYPE_LAYER_OFFSET;
-    }
-
     void disposeChannelsLw() {
         mService.mInputManager.unregisterInputChannel(mServerChannel);
         mClientChannel.dispose();
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f9ff2e3..b9a9c12 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -264,7 +264,6 @@
         inputWindowHandle.hasFocus = hasFocus;
         inputWindowHandle.hasWallpaper = hasWallpaper;
         inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
-        inputWindowHandle.layer = child.mLayer;
         inputWindowHandle.ownerPid = child.mSession.mPid;
         inputWindowHandle.ownerUid = child.mSession.mUid;
         inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
@@ -499,8 +498,7 @@
                 }
             }
 
-            if (mAddInputConsumerHandle
-                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
+            if (mAddInputConsumerHandle) {
                 navInputConsumer.show(mInputTransaction, w);
                 mAddInputConsumerHandle = false;
             }
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index a867a5d4..2a1d271 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -274,7 +274,6 @@
         mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, display.getDisplayId());
         mDragWindowHandle.name = TAG;
         mDragWindowHandle.token = mServerChannel.getToken();
-        mDragWindowHandle.layer = mService.getDragLayerLocked();
         mDragWindowHandle.layoutParamsFlags = 0;
         mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
         mDragWindowHandle.dispatchingTimeoutNanos =
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ab3419c..53c5ebd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -59,7 +59,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -630,10 +629,6 @@
 
     boolean mDisableTransitionAnimation;
 
-    int getDragLayerLocked() {
-        return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
-    }
-
     class RotationWatcher {
         final IRotationWatcher mWatcher;
         final IBinder.DeathRecipient mDeathRecipient;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1536816..272edf7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -303,6 +303,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -2266,23 +2267,23 @@
     @VisibleForTesting
     DevicePolicyManagerService(Injector injector) {
         mInjector = injector;
-        mContext = Preconditions.checkNotNull(injector.mContext);
-        mHandler = new Handler(Preconditions.checkNotNull(injector.getMyLooper()));
+        mContext = Objects.requireNonNull(injector.mContext);
+        mHandler = new Handler(Objects.requireNonNull(injector.getMyLooper()));
 
         mConstantsObserver = new DevicePolicyConstantsObserver(mHandler);
         mConstantsObserver.register();
         mConstants = loadConstants();
 
-        mOwners = Preconditions.checkNotNull(injector.newOwners());
+        mOwners = Objects.requireNonNull(injector.newOwners());
 
-        mUserManager = Preconditions.checkNotNull(injector.getUserManager());
-        mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal());
-        mUsageStatsManagerInternal = Preconditions.checkNotNull(
+        mUserManager = Objects.requireNonNull(injector.getUserManager());
+        mUserManagerInternal = Objects.requireNonNull(injector.getUserManagerInternal());
+        mUsageStatsManagerInternal = Objects.requireNonNull(
                 injector.getUsageStatsManagerInternal());
-        mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
-        mIPlatformCompat = Preconditions.checkNotNull(injector.getIPlatformCompat());
-        mIPermissionManager = Preconditions.checkNotNull(injector.getIPermissionManager());
-        mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
+        mIPackageManager = Objects.requireNonNull(injector.getIPackageManager());
+        mIPlatformCompat = Objects.requireNonNull(injector.getIPlatformCompat());
+        mIPermissionManager = Objects.requireNonNull(injector.getIPermissionManager());
+        mTelephonyManager = Objects.requireNonNull(injector.getTelephonyManager());
 
         mLocalService = new LocalService();
         mLockPatternUtils = injector.newLockPatternUtils();
@@ -4047,7 +4048,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
+        Objects.requireNonNull(adminReceiver, "ComponentName is null");
         enforceShell("forceRemoveActiveAdmin");
         mInjector.binderWithCleanCallingIdentity(() -> {
             synchronized (getLockObject()) {
@@ -4164,7 +4165,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         validateQualityConstant(quality);
 
         final int userId = mInjector.userHandleGetCallingUserId();
@@ -4377,7 +4378,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4419,7 +4420,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4451,7 +4452,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkArgumentNonnegative(timeout, "Timeout must be >= 0 ms");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
@@ -4633,7 +4634,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             final ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4663,7 +4664,7 @@
 
     @Override
     public void setPasswordMinimumLowerCase(ComponentName who, int length, boolean parent) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4696,7 +4697,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4728,7 +4729,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4760,7 +4761,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -4792,7 +4793,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -5019,7 +5020,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             // This API can only be called by an active device admin,
@@ -5259,7 +5260,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             final ActiveAdmin ap = getActiveAdminForCallerLocked(
@@ -5360,7 +5361,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
         // timeoutMs with value 0 means that the admin doesn't participate
         // timeoutMs is clamped to the interval in case the internal constants change in the future
@@ -6108,7 +6109,7 @@
     @Override
     public void setDelegatedScopes(ComponentName who, String delegatePackage,
             List<String> scopeList) throws SecurityException {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(delegatePackage, "Delegate package is null or empty");
         Preconditions.checkCollectionElementsNotNull(scopeList, "Scopes");
         // Remove possible duplicates.
@@ -6206,7 +6207,7 @@
     @NonNull
     public List<String> getDelegatedScopes(ComponentName who,
             String delegatePackage) throws SecurityException {
-        Preconditions.checkNotNull(delegatePackage, "Delegate package is null");
+        Objects.requireNonNull(delegatePackage, "Delegate package is null");
 
         // Retrieve the user ID of the calling process.
         final int callingUid = mInjector.binderGetCallingUid();
@@ -6246,8 +6247,8 @@
     @NonNull
     public List<String> getDelegatePackages(ComponentName who, String scope)
             throws SecurityException {
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(scope, "Scope is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(scope, "Scope is null");
         if (!Arrays.asList(DELEGATIONS).contains(scope)) {
             throw new IllegalArgumentException("Unexpected delegation scope: " + scope);
         }
@@ -6329,7 +6330,7 @@
      * @return {@code true} if the calling process is a delegate of {@code scope}.
      */
     private boolean isCallerDelegate(String callerPackage, int callerUid, String scope) {
-        Preconditions.checkNotNull(callerPackage, "callerPackage is null");
+        Objects.requireNonNull(callerPackage, "callerPackage is null");
         if (!Arrays.asList(DELEGATIONS).contains(scope)) {
             throw new IllegalArgumentException("Unexpected delegation scope: " + scope);
         }
@@ -6410,7 +6411,7 @@
      */
     private void setDelegatedScopePreO(ComponentName who,
             String delegatePackage, String scope) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
@@ -6938,7 +6939,7 @@
             return null;
         }
         synchronized (getLockObject()) {
-            Preconditions.checkNotNull(who, "ComponentName is null");
+            Objects.requireNonNull(who, "ComponentName is null");
 
             // Only check if system user has set global proxy. We don't allow other users to set it.
             DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
@@ -7066,7 +7067,7 @@
         if (!mHasFeature) {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             // Check for permissions
@@ -7220,7 +7221,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
@@ -7287,7 +7288,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -7347,7 +7348,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         // TODO (b/145286957) Refactor security checks
         enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
 
@@ -7369,7 +7370,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
 
         return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
@@ -7383,7 +7384,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         // TODO (b/145286957) Refactor security checks
         enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
 
@@ -7405,7 +7406,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
 
         return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
@@ -7416,7 +7417,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         // Allow setting this policy to true only if there is a split system user.
         if (forceEphemeralUsers && !mInjector.userManagerIsSplitSystemUser()) {
             throw new UnsupportedOperationException(
@@ -7443,7 +7444,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             final ActiveAdmin deviceOwner =
                     getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -7472,7 +7473,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         // TODO: If an unaffiliated user is removed, the admin will be able to request a bugreport
         // which could still contain data related to that user. Should we disallow that, e.g. until
@@ -7709,7 +7710,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
@@ -7779,7 +7780,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         if (isManagedProfile(userHandle)) {
             if (parent) {
@@ -7867,7 +7868,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(packageList, "packageList is null");
+        Objects.requireNonNull(packageList, "packageList is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             // Ensure the caller is a DO or a keep uninstalled packages delegate.
@@ -8104,7 +8105,7 @@
 
     @Override
     public void clearDeviceOwner(String packageName) {
-        Preconditions.checkNotNull(packageName, "packageName is null");
+        Objects.requireNonNull(packageName, "packageName is null");
         final int callingUid = mInjector.binderGetCallingUid();
         try {
             int uid = mInjector.getPackageManager().getPackageUidAsUser(packageName,
@@ -8259,7 +8260,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         final int userId = mInjector.userHandleGetCallingUserId();
         enforceNotManagedProfile(userId, "clear profile owner");
@@ -8300,7 +8301,7 @@
 
     @Override
     public void setDeviceOwnerLockScreenInfo(ComponentName who, CharSequence info) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         if (!mHasFeature) {
             return;
         }
@@ -8470,7 +8471,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             // Check if this is the profile owner who is calling
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -8497,7 +8498,7 @@
 
     @Override
     public void setProfileName(ComponentName who, String profileName) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceProfileOrDeviceOwner(who);
 
         final int userId = UserHandle.getCallingUserId();
@@ -9090,7 +9091,7 @@
     @Override
     public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
             ComponentName activity) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9116,7 +9117,7 @@
 
     @Override
     public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9135,7 +9136,7 @@
 
     @Override
     public void setDefaultSmsApplication(ComponentName admin, String packageName) {
-        Preconditions.checkNotNull(admin, "ComponentName is null");
+        Objects.requireNonNull(admin, "ComponentName is null");
         enforceDeviceOwner(admin);
         mInjector.binderWithCleanCallingIdentity(() ->
                 SmsApplication.setDefaultApplication(packageName, mContext));
@@ -9190,8 +9191,8 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return;
         }
-        Preconditions.checkNotNull(admin, "admin is null");
-        Preconditions.checkNotNull(agent, "agent is null");
+        Objects.requireNonNull(admin, "admin is null");
+        Objects.requireNonNull(agent, "agent is null");
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
@@ -9207,7 +9208,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return null;
         }
-        Preconditions.checkNotNull(agent, "agent null");
+        Objects.requireNonNull(agent, "agent null");
         enforceFullCrossUsersPermission(userHandle);
 
         synchronized (getLockObject()) {
@@ -9259,7 +9260,7 @@
 
     @Override
     public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
@@ -9281,7 +9282,7 @@
 
     @Override
     public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         int callingUserId = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9330,7 +9331,7 @@
 
     @Override
     public void clearCrossProfileIntentFilters(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         int callingUserId = UserHandle.getCallingUserId();
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -9407,7 +9408,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         if (packageList != null) {
             int userId = UserHandle.getCallingUserId();
@@ -9460,7 +9461,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -9536,7 +9537,7 @@
         if (!mHasFeature) {
             return true;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(packageName, "packageName is null");
         enforceSystemCaller("query if an accessibility service is disabled by admin");
 
@@ -9587,7 +9588,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (packageList != null) {
             List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
@@ -9627,7 +9628,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -9681,7 +9682,7 @@
         if (!mHasFeature) {
             return true;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(packageName, "packageName is null");
         enforceSystemCaller("query if an input method is disabled by admin");
 
@@ -9704,7 +9705,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (!isManagedProfile(callingUserId)) {
@@ -9725,7 +9726,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -9787,8 +9788,8 @@
     @Override
     public UserHandle createAndManageUser(ComponentName admin, String name,
             ComponentName profileOwner, PersistableBundle adminExtras, int flags) {
-        Preconditions.checkNotNull(admin, "admin is null");
-        Preconditions.checkNotNull(profileOwner, "profileOwner is null");
+        Objects.requireNonNull(admin, "admin is null");
+        Objects.requireNonNull(profileOwner, "profileOwner is null");
         if (!admin.getPackageName().equals(profileOwner.getPackageName())) {
             throw new IllegalArgumentException("profileOwner " + profileOwner + " and admin "
                     + admin + " are not in the same package");
@@ -9919,8 +9920,8 @@
 
     @Override
     public boolean removeUser(ComponentName who, UserHandle userHandle) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(userHandle, "UserHandle is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(userHandle, "UserHandle is null");
         enforceDeviceOwner(who);
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -9953,7 +9954,7 @@
 
     @Override
     public boolean switchUser(ComponentName who, UserHandle userHandle) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -9976,8 +9977,8 @@
 
     @Override
     public int startUserInBackground(ComponentName who, UserHandle userHandle) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(userHandle, "UserHandle is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(userHandle, "UserHandle is null");
         enforceDeviceOwner(who);
 
         final int userId = userHandle.getIdentifier();
@@ -10008,8 +10009,8 @@
 
     @Override
     public int stopUser(ComponentName who, UserHandle userHandle) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(userHandle, "UserHandle is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(userHandle, "UserHandle is null");
         enforceDeviceOwner(who);
 
         final int userId = userHandle.getIdentifier();
@@ -10023,7 +10024,7 @@
 
     @Override
     public int logoutUser(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
@@ -10077,7 +10078,7 @@
 
     @Override
     public List<UserHandle> getSecondaryUsers(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
         return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -10096,7 +10097,7 @@
 
     @Override
     public boolean isEphemeralUser(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceProfileOrDeviceOwner(who);
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
@@ -10178,7 +10179,7 @@
     @Override
     public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner,
             boolean parent) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         if (!UserRestrictionsUtils.isValidRestriction(key)) {
             return;
         }
@@ -10324,7 +10325,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             final ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(who,
@@ -10559,7 +10560,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10653,7 +10654,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10674,7 +10675,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10696,7 +10697,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10717,7 +10718,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10797,7 +10798,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10818,7 +10819,7 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -10840,8 +10841,8 @@
     @Override
     public void setLockTaskPackages(ComponentName who, String[] packages)
             throws SecurityException {
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(packages, "packages is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(packages, "packages is null");
 
         synchronized (getLockObject()) {
             enforceCanCallLockTaskLocked(who);
@@ -10861,7 +10862,7 @@
 
     @Override
     public String[] getLockTaskPackages(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         final int userHandle = mInjector.binderGetCallingUserHandle().getIdentifier();
         synchronized (getLockObject()) {
@@ -10881,7 +10882,7 @@
 
     @Override
     public void setLockTaskFeatures(ComponentName who, int flags) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         // Throw if Overview is used without Home.
         boolean hasHome = (flags & LOCK_TASK_FEATURE_HOME) != 0;
@@ -10908,7 +10909,7 @@
 
     @Override
     public int getLockTaskFeatures(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             enforceCanCallLockTaskLocked(who);
@@ -10978,7 +10979,7 @@
 
     @Override
     public void setGlobalSetting(ComponentName who, String setting, String value) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_GLOBAL_SETTING)
@@ -11018,7 +11019,7 @@
 
     @Override
     public void setSystemSetting(ComponentName who, String setting, String value) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
 
         synchronized (getLockObject()) {
@@ -11038,7 +11039,7 @@
 
     @Override
     public void setLocationEnabled(ComponentName who, boolean locationEnabled) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
         UserHandle userHandle = mInjector.binderGetCallingUserHandle();
@@ -11057,7 +11058,7 @@
 
     @Override
     public boolean setTime(ComponentName who, long millis) {
-        Preconditions.checkNotNull(who, "ComponentName is null in setTime");
+        Objects.requireNonNull(who, "ComponentName is null in setTime");
         enforceDeviceOwner(who);
         // Don't allow set time when auto time is on.
         if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) == 1) {
@@ -11072,7 +11073,7 @@
 
     @Override
     public boolean setTimeZone(ComponentName who, String timeZone) {
-        Preconditions.checkNotNull(who, "ComponentName is null in setTimeZone");
+        Objects.requireNonNull(who, "ComponentName is null in setTimeZone");
         enforceDeviceOwner(who);
         // Don't allow set timezone when auto timezone is on.
         if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) {
@@ -11088,7 +11089,7 @@
 
     @Override
     public void setSecureSetting(ComponentName who, String setting, String value) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         int callingUserId = mInjector.userHandleGetCallingUserId();
 
         synchronized (getLockObject()) {
@@ -11159,7 +11160,7 @@
 
     @Override
     public void setMasterVolumeMuted(ComponentName who, boolean on) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
@@ -11173,7 +11174,7 @@
 
     @Override
     public boolean isMasterVolumeMuted(ComponentName who) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
@@ -11186,7 +11187,7 @@
     @Override
     public void setUserIcon(ComponentName who, Bitmap icon) {
         synchronized (getLockObject()) {
-            Preconditions.checkNotNull(who, "ComponentName is null");
+            Objects.requireNonNull(who, "ComponentName is null");
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             int userId = UserHandle.getCallingUserId();
@@ -11201,7 +11202,7 @@
 
     @Override
     public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -11664,7 +11665,7 @@
 
     @Override
     public Intent createAdminSupportIntent(String restriction) {
-        Preconditions.checkNotNull(restriction);
+        Objects.requireNonNull(restriction);
         final int uid = mInjector.binderGetCallingUid();
         final int userId = UserHandle.getUserId(uid);
         Intent intent = null;
@@ -11922,7 +11923,7 @@
 
     @Override
     public SystemUpdateInfo getPendingSystemUpdate(ComponentName admin) {
-        Preconditions.checkNotNull(admin, "ComponentName is null");
+        Objects.requireNonNull(admin, "ComponentName is null");
         enforceProfileOrDeviceOwner(admin);
 
         return mOwners.getSystemUpdateInfo();
@@ -11964,7 +11965,7 @@
     public void setPermissionGrantState(ComponentName admin, String callerPackage,
             String packageName, String permission, int grantState, RemoteCallback callback)
             throws RemoteException {
-        Preconditions.checkNotNull(callback);
+        Objects.requireNonNull(callback);
 
         UserHandle user = mInjector.binderGetCallingUserHandle();
         synchronized (getLockObject()) {
@@ -12099,7 +12100,7 @@
 
     @Override
     public boolean isProvisioningAllowed(String action, String packageName) {
-        Preconditions.checkNotNull(packageName);
+        Objects.requireNonNull(packageName);
 
         final int callingUid = mInjector.binderGetCallingUid();
         final long ident = mInjector.binderClearCallingIdentity();
@@ -12119,7 +12120,7 @@
 
     @Override
     public int checkProvisioningPreCondition(String action, String packageName) {
-        Preconditions.checkNotNull(packageName);
+        Objects.requireNonNull(packageName);
         enforceCanManageProfileAndDeviceOwners();
         return checkProvisioningPreConditionSkipPermission(action, packageName);
     }
@@ -12359,7 +12360,7 @@
 
     @Override
     public void reboot(ComponentName admin) {
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         // Make sure caller has DO.
         enforceDeviceOwner(admin);
         mInjector.binderWithCleanCallingIdentity(() -> {
@@ -12380,7 +12381,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
@@ -12400,7 +12401,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
             return admin.shortSupportMessage;
@@ -12412,7 +12413,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
@@ -12432,7 +12433,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForUidLocked(who, mInjector.binderGetCallingUid());
             return admin.longSupportMessage;
@@ -12444,7 +12445,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceSystemCaller("query support message for user");
 
         synchronized (getLockObject()) {
@@ -12461,7 +12462,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceSystemCaller("query support message for user");
 
         synchronized (getLockObject()) {
@@ -12478,7 +12479,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
         enforceManagedProfile(userHandle, "set organization color");
         synchronized (getLockObject()) {
@@ -12513,7 +12514,7 @@
         if (!mHasFeature) {
             return ActiveAdmin.DEF_ORGANIZATION_COLOR;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -12542,7 +12543,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         final int userHandle = mInjector.userHandleGetCallingUserId();
 
         synchronized (getLockObject()) {
@@ -12561,7 +12562,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
         synchronized (getLockObject()) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -12599,8 +12600,8 @@
 
     @Override
     public List<String> setMeteredDataDisabledPackages(ComponentName who, List<String> packageNames) {
-        Preconditions.checkNotNull(who);
-        Preconditions.checkNotNull(packageNames);
+        Objects.requireNonNull(who);
+        Objects.requireNonNull(packageNames);
 
         if (!mHasFeature) {
             return packageNames;
@@ -12646,7 +12647,7 @@
 
     @Override
     public List<String> getMeteredDataDisabledPackages(ComponentName who) {
-        Preconditions.checkNotNull(who);
+        Objects.requireNonNull(who);
 
         if (!mHasFeature) {
             return new ArrayList<>();
@@ -12662,7 +12663,7 @@
     @Override
     public boolean isMeteredDataDisabledPackageForUser(ComponentName who,
             String packageName, int userId) {
-        Preconditions.checkNotNull(who);
+        Objects.requireNonNull(who);
 
         if (!mHasFeature) {
             return false;
@@ -12688,7 +12689,7 @@
     public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
         // As the caller is the system, it must specify the component name of the profile owner
         // as a sanity / safety check.
-        Preconditions.checkNotNull(who);
+        Objects.requireNonNull(who);
 
         if (!mHasFeature) {
             return;
@@ -12808,7 +12809,7 @@
             return Collections.emptyList();
         }
 
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             return new ArrayList<String>(
@@ -12877,7 +12878,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -12907,7 +12908,7 @@
 
         synchronized (getLockObject()) {
             if (!isCallerWithSystemUid()) {
-                Preconditions.checkNotNull(admin);
+                Objects.requireNonNull(admin);
                 getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
             }
             return mInjector.securityLogGetLoggingEnabledProperty();
@@ -12931,7 +12932,7 @@
             return null;
         }
 
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         ensureDeviceOwnerAndAllUsersAffiliated(admin);
 
         DevicePolicyEventLogger
@@ -12961,7 +12962,7 @@
             return null;
         }
 
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         ensureDeviceOwnerAndAllUsersAffiliated(admin);
 
         if (!mInjector.securityLogGetLoggingEnabledProperty()) {
@@ -13206,7 +13207,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         enforceProfileOrDeviceOwner(admin);
         int userId = mInjector.userHandleGetCallingUserId();
         toggleBackupServiceActive(userId, enabled);
@@ -13214,7 +13215,7 @@
 
     @Override
     public boolean isBackupServiceEnabled(ComponentName admin) {
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
         if (!mHasFeature) {
             return true;
         }
@@ -13239,14 +13240,14 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkNotNull(admin);
-        Preconditions.checkNotNull(caller);
-        Preconditions.checkNotNull(serviceIntent);
+        Objects.requireNonNull(admin);
+        Objects.requireNonNull(caller);
+        Objects.requireNonNull(serviceIntent);
         Preconditions.checkArgument(
                 serviceIntent.getComponent() != null || serviceIntent.getPackage() != null,
                 "Service intent must be explicit (with a package name or component): "
                         + serviceIntent);
-        Preconditions.checkNotNull(connection);
+        Objects.requireNonNull(connection);
         Preconditions.checkArgument(mInjector.userHandleGetCallingUserId() != targetUserId,
                 "target user id must be different from the calling user id");
 
@@ -13290,7 +13291,7 @@
         if (!mHasFeature) {
             return Collections.emptyList();
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -13755,7 +13756,7 @@
         if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
             return false;
         }
-        Preconditions.checkNotNull(token);
+        Objects.requireNonNull(token);
         synchronized (getLockObject()) {
             final int userHandle = mInjector.userHandleGetCallingUserId();
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -13791,9 +13792,9 @@
     @Override
     public void clearApplicationUserData(ComponentName admin, String packageName,
             IPackageDataObserver callback) {
-        Preconditions.checkNotNull(admin, "ComponentName is null");
-        Preconditions.checkNotNull(packageName, "packageName is null");
-        Preconditions.checkNotNull(callback, "callback is null");
+        Objects.requireNonNull(admin, "ComponentName is null");
+        Objects.requireNonNull(packageName, "packageName is null");
+        Objects.requireNonNull(callback, "callback is null");
         enforceProfileOrDeviceOwner(admin);
         final int userId = UserHandle.getCallingUserId();
 
@@ -13824,7 +13825,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
             ActiveAdmin deviceOwner =
@@ -13865,8 +13866,8 @@
             return;
         }
 
-        Preconditions.checkNotNull(admin, "Admin cannot be null.");
-        Preconditions.checkNotNull(target, "Target cannot be null.");
+        Objects.requireNonNull(admin, "Admin cannot be null.");
+        Objects.requireNonNull(target, "Target cannot be null.");
 
         enforceProfileOrDeviceOwner(admin);
 
@@ -14001,7 +14002,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         final String startUserSessionMessageString =
                 startUserSessionMessage != null ? startUserSessionMessage.toString() : null;
@@ -14026,7 +14027,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         final String endUserSessionMessageString =
                 endUserSessionMessage != null ? endUserSessionMessage.toString() : null;
@@ -14051,7 +14052,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
             final ActiveAdmin deviceOwner =
@@ -14065,7 +14066,7 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkNotNull(admin);
+        Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
             final ActiveAdmin deviceOwner =
@@ -14108,8 +14109,8 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return -1;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
-        Preconditions.checkNotNull(apnSetting, "ApnSetting is null in addOverrideApn");
+        Objects.requireNonNull(who, "ComponentName is null in addOverrideApn");
+        Objects.requireNonNull(apnSetting, "ApnSetting is null in addOverrideApn");
         enforceDeviceOwner(who);
 
         int operatedId = -1;
@@ -14132,8 +14133,8 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
-        Preconditions.checkNotNull(apnSetting, "ApnSetting is null in updateOverrideApn");
+        Objects.requireNonNull(who, "ComponentName is null in updateOverrideApn");
+        Objects.requireNonNull(apnSetting, "ApnSetting is null in updateOverrideApn");
         enforceDeviceOwner(who);
 
         if (apnId < 0) {
@@ -14150,7 +14151,7 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
+        Objects.requireNonNull(who, "ComponentName is null in removeOverrideApn");
         enforceDeviceOwner(who);
 
         return removeOverrideApnUnchecked(apnId);
@@ -14171,7 +14172,7 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return Collections.emptyList();
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
+        Objects.requireNonNull(who, "ComponentName is null in getOverrideApns");
         enforceDeviceOwner(who);
 
         return getOverrideApnsUnchecked();
@@ -14202,7 +14203,7 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
+        Objects.requireNonNull(who, "ComponentName is null in setOverrideApnEnabled");
         enforceDeviceOwner(who);
 
         setOverrideApnsEnabledUnchecked(enabled);
@@ -14220,7 +14221,7 @@
         if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
+        Objects.requireNonNull(who, "ComponentName is null in isOverrideApnEnabled");
         enforceDeviceOwner(who);
 
         Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity(
@@ -14304,7 +14305,7 @@
             return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
         }
 
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
         final int returnCode;
@@ -14342,7 +14343,7 @@
             return PRIVATE_DNS_MODE_UNKNOWN;
         }
 
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
         String currentMode = mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE);
         if (currentMode == null) {
@@ -14366,7 +14367,7 @@
             return null;
         }
 
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
         return mInjector.settingsGlobalGetString(PRIVATE_DNS_SPECIFIER);
@@ -14404,7 +14405,7 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             final ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -14425,7 +14426,7 @@
         if (!mHasFeature) {
             return Collections.emptyList();
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             final ActiveAdmin admin = getActiveAdminForCallerLocked(
@@ -14479,8 +14480,8 @@
         if (!mHasFeature) {
             return;
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
-        Preconditions.checkNotNull(packageNames, "Package names is null");
+        Objects.requireNonNull(who, "ComponentName is null");
+        Objects.requireNonNull(packageNames, "Package names is null");
         synchronized (getLockObject()) {
             final ActiveAdmin admin =
                     getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
@@ -14494,7 +14495,7 @@
         if (!mHasFeature) {
             return Collections.emptyList();
         }
-        Preconditions.checkNotNull(who, "ComponentName is null");
+        Objects.requireNonNull(who, "ComponentName is null");
 
         synchronized (getLockObject()) {
             final ActiveAdmin admin = getActiveAdminForCallerLocked(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
index dd3bfc3..4b66bea 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/TransferOwnershipMetadataManager.java
@@ -39,6 +39,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.Objects;
 
 /**
  * Handles reading and writing of the owner transfer metadata file.
@@ -185,8 +186,8 @@
                 @NonNull int userId, @NonNull String adminType) {
             this.sourceComponent = sourceComponent;
             this.targetComponent = targetComponent;
-            Preconditions.checkNotNull(sourceComponent);
-            Preconditions.checkNotNull(targetComponent);
+            Objects.requireNonNull(sourceComponent);
+            Objects.requireNonNull(targetComponent);
             Preconditions.checkStringNotEmpty(adminType);
             this.userId = userId;
             this.adminType = adminType;
@@ -199,7 +200,7 @@
         }
 
         private static ComponentName unflattenComponentUnchecked(String flatComponent) {
-            Preconditions.checkNotNull(flatComponent);
+            Objects.requireNonNull(flatComponent);
             return ComponentName.unflattenFromString(flatComponent);
         }
 
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index d34f783..bbc6bdb 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -26,6 +26,11 @@
         <option name="test-file-name" value="SimpleServiceTestApp.apk" />
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="AppIntegrityManagerServiceTestApp.apk->/data/local/tmp/AppIntegrityManagerServiceTestApp.apk" />
+    </target_preparer>
+
     <option name="test-tag" value="FrameworksServicesTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.servicestests" />
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
deleted file mode 100644
index 6345c98..0000000
--- a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
+++ /dev/null
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 17e5832..09a6819 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -17,7 +17,6 @@
 
 import com.google.common.base.Objects;
 
-import com.android.internal.util.Preconditions;
 import com.android.server.pm.UserRestrictionsUtils;
 
 import android.content.ComponentName;
@@ -107,7 +106,7 @@
     }
 
     public static Bundle checkUserRestrictions(String... keys) {
-        final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys));
+        final Bundle expected = DpmTestUtils.newRestrictions(java.util.Objects.requireNonNull(keys));
         final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
             @Override
             public boolean matches(Object item) {
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index a2376a6..604efc4 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -32,6 +32,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 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;
@@ -64,7 +65,6 @@
 import com.android.server.integrity.model.IntegrityCheckResult;
 import com.android.server.testutils.TestUtils;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -75,9 +75,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.StandardCopyOption;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
@@ -86,7 +83,8 @@
 /** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
 @RunWith(AndroidJUnit4.class)
 public class AppIntegrityManagerServiceImplTest {
-    private static final String TEST_DIR = "AppIntegrityManagerServiceImplTest";
+    private static final String TEST_APP_PATH =
+            "/data/local/tmp/AppIntegrityManagerServiceTestApp.apk";
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
     private static final String VERSION = "version";
@@ -97,13 +95,19 @@
     private static final String INSTALLER = TEST_FRAMEWORK_PACKAGE;
     // These are obtained by running the test and checking logcat.
     private static final String APP_CERT =
-            "949ADC6CB92FF09E3784D6E9504F26F9BEAC06E60D881D55A6A81160F9CD6FD1";
+            "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
     private static final String INSTALLER_CERT =
             "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
     // We use SHA256 for package names longer than 32 characters.
     private static final String INSTALLER_SHA256 =
             "786933C28839603EB48C50B2A688DC6BE52C833627CB2731FF8466A2AE9F94CD";
 
+    private static final String PLAY_STORE_PKG = "com.android.vending";
+    private static final String ADB_INSTALLER = "adb";
+    private static final String PLAY_STORE_CERT =
+            "play_store_cert";
+    private static final String ADB_CERT = "";
+
     @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
     @Mock PackageManagerInternal mPackageManagerInternal;
@@ -122,11 +126,7 @@
 
     @Before
     public void setup() throws Exception {
-        mTestApk = File.createTempFile("TestApk", /* suffix= */ null);
-        mTestApk.deleteOnExit();
-        try (InputStream inputStream = mRealContext.getAssets().open(TEST_DIR + "/test.apk")) {
-            Files.copy(inputStream, mTestApk.toPath(), StandardCopyOption.REPLACE_EXISTING);
-        }
+        mTestApk = new File(TEST_APP_PATH);
 
         mService =
                 new AppIntegrityManagerServiceImpl(
@@ -141,11 +141,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
         when(mMockContext.getResources()).thenReturn(mMockResources);
         when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mTestApk.delete();
+        when(mIntegrityFileManager.initialized()).thenReturn(true);
     }
 
     // This is not a test of the class, but more of a safeguard that we don't block any install in
@@ -310,10 +306,10 @@
         assertEquals(INSTALLER_CERT, appInstallMetadata.getInstallerCertificate());
         assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode());
         assertFalse(appInstallMetadata.isPreInstalled());
-        // These are hardcoded in the test apk
+        // These are hardcoded in the test apk android manifest
         assertEquals(2, allowedInstallers.size());
-        assertEquals("cert_1", allowedInstallers.get("store_1"));
-        assertEquals("cert_2", allowedInstallers.get("store_2"));
+        assertEquals(PLAY_STORE_CERT, allowedInstallers.get(PLAY_STORE_PKG));
+        assertEquals(ADB_CERT, allowedInstallers.get(ADB_INSTALLER));
     }
 
     @Test
@@ -356,6 +352,25 @@
                         1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
     }
 
+    @Test
+    public void handleBroadcast_notInitialized() throws Exception {
+        when(mIntegrityFileManager.initialized()).thenReturn(false);
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        verify(mMockContext)
+                .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+        Intent intent = makeVerificationIntent();
+        when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+        broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+        runJobInHandler();
+
+        verify(mPackageManagerInternal)
+                .setIntegrityVerificationResult(
+                        1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+        verify(mSpyPackageManager, never()).getPackageArchiveInfo(any(), anyInt());
+    }
+
     private void whitelistUsAsRuleProvider() {
         Resources mockResources = mock(Resources.class);
         when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
new file mode 100644
index 0000000..63189e7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2020 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.integrity;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItems;
+import static org.junit.Assert.assertThat;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
+import android.util.Slog;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.integrity.parser.RuleXmlParser;
+import com.android.server.integrity.serializer.RuleXmlSerializer;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/** Unit test for {@link IntegrityFileManager} */
+@RunWith(AndroidJUnit4.class)
+public class IntegrityFileManagerTest {
+    private static final String TAG = "IntegrityFileManagerTest";
+
+    private static final String VERSION = "version";
+    private static final String RULE_PROVIDER = "rule_provider";
+
+    private File mTmpDir;
+
+    // under test
+    private IntegrityFileManager mIntegrityFileManager;
+
+    @Before
+    public void setUp() throws Exception {
+        mTmpDir = Files.createTempDirectory("IntegrityFileManagerTest").toFile();
+        Slog.i(TAG, "Using temp directory " + mTmpDir);
+
+        // Use Xml Parser/Serializer to help with debugging since we can just print the file.
+        mIntegrityFileManager =
+                new IntegrityFileManager(
+                        new RuleXmlParser(), new RuleXmlSerializer(), mTmpDir);
+        Files.walk(mTmpDir.toPath())
+                .forEach(
+                        path -> {
+                            Slog.i(TAG, "before " + path);
+                        });
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        Files.walk(mTmpDir.toPath())
+                .forEach(
+                        path -> {
+                            Slog.i(TAG, "after " + path);
+                        });
+        // Sorting paths in reverse order guarantees that we delete inside files before deleting
+        // directory.
+        Files.walk(mTmpDir.toPath())
+                .sorted(Comparator.reverseOrder())
+                .map(Path::toFile)
+                .forEach(File::delete);
+    }
+
+    @Test
+    public void testGetMetadata() throws Exception {
+        assertNull(mIntegrityFileManager.readMetadata());
+        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+
+        assertNotNull(mIntegrityFileManager.readMetadata());
+        assertEquals(VERSION, mIntegrityFileManager.readMetadata().getVersion());
+        assertEquals(RULE_PROVIDER, mIntegrityFileManager.readMetadata().getRuleProvider());
+    }
+
+    @Test
+    public void testGetRules() throws Exception {
+        String packageName = "package";
+        String packageCert = "cert";
+        int version = 123;
+        Rule packageNameRule =
+                new Rule(
+                        new StringAtomicFormula(
+                                AtomicFormula.PACKAGE_NAME,
+                                packageName,
+                                /* isHashedValue= */ false),
+                        Rule.DENY);
+        Rule packageCertRule =
+                new Rule(
+                        new StringAtomicFormula(
+                                AtomicFormula.APP_CERTIFICATE,
+                                packageCert,
+                                /* isHashedValue= */ false),
+                        Rule.DENY);
+        Rule versionCodeRule =
+                new Rule(
+                        new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
+                        Rule.DENY);
+        Rule randomRule =
+                new Rule(
+                        new CompoundFormula(
+                                CompoundFormula.OR,
+                                Arrays.asList(
+                                        new StringAtomicFormula(
+                                                AtomicFormula.PACKAGE_NAME,
+                                                "abc",
+                                                /* isHashedValue= */ false),
+                                        new IntAtomicFormula(
+                                                AtomicFormula.VERSION_CODE,
+                                                AtomicFormula.LE,
+                                                version))),
+                        Rule.DENY);
+        // We will test the specifics of indexing in other classes. Here, we just require that all
+        // rules that are related to the given AppInstallMetadata are returned and do not assert
+        // anything on other rules.
+        List<Rule> rules =
+                Arrays.asList(packageNameRule, packageCertRule, versionCodeRule, randomRule);
+        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, rules);
+
+        AppInstallMetadata appInstallMetadata = new AppInstallMetadata.Builder()
+                .setPackageName(packageName)
+                .setAppCertificate(packageCert)
+                .setVersionCode(version)
+                .setInstallerName("abc")
+                .setInstallerCertificate("abc")
+                .setIsPreInstalled(true)
+                .build();
+        List<Rule> rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata);
+
+        assertThat(rulesFetched, hasItems(
+                equalTo(packageNameRule),
+                equalTo(packageCertRule),
+                equalTo(versionCodeRule)
+        ));
+    }
+
+    @Test
+    public void testIsInitialized() throws Exception {
+        assertFalse(mIntegrityFileManager.initialized());
+        mIntegrityFileManager.writeRules(VERSION, RULE_PROVIDER, Collections.EMPTY_LIST);
+        assertTrue(mIntegrityFileManager.initialized());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
index 94e11c6..55fada4 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
@@ -38,8 +38,10 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 
 /** Unit tests for {@link RuleIndexingDetailsIdentifier}. */
 @RunWith(JUnit4.class)
@@ -138,14 +140,16 @@
         List<Rule> ruleList = new ArrayList();
         ruleList.add(RULE_WITH_PACKAGE_NAME);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         // Verify the resulting map content.
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
         assertThat(result.get(NOT_INDEXED)).isEmpty();
         assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
-        assertThat(result.get(PACKAGE_NAME_INDEXED)).containsExactly(RULE_WITH_PACKAGE_NAME);
+        assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly(SAMPLE_PACKAGE_NAME);
+        assertThat(result.get(PACKAGE_NAME_INDEXED).get(SAMPLE_PACKAGE_NAME))
+                .containsExactly(RULE_WITH_PACKAGE_NAME);
     }
 
     @Test
@@ -153,13 +157,16 @@
         List<Rule> ruleList = new ArrayList();
         ruleList.add(RULE_WITH_APP_CERTIFICATE);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
         assertThat(result.get(NOT_INDEXED)).isEmpty();
         assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
-        assertThat(result.get(APP_CERTIFICATE_INDEXED)).containsExactly(RULE_WITH_APP_CERTIFICATE);
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet())
+                .containsExactly(SAMPLE_APP_CERTIFICATE);
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).get(SAMPLE_APP_CERTIFICATE))
+                .containsExactly(RULE_WITH_APP_CERTIFICATE);
     }
 
     @Test
@@ -167,13 +174,14 @@
         List<Rule> ruleList = new ArrayList();
         ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
         assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
         assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
-        assertThat(result.get(NOT_INDEXED)).containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS);
+        assertThat(result.get(NOT_INDEXED).get("N/A"))
+                .containsExactly(RULE_WITH_INSTALLER_RESTRICTIONS);
     }
 
     @Test
@@ -181,13 +189,14 @@
         List<Rule> ruleList = new ArrayList();
         ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
         assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
         assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
-        assertThat(result.get(NOT_INDEXED)).containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS);
+        assertThat(result.get(NOT_INDEXED).get("N/A"))
+                .containsExactly(RULE_WITH_NONSTRING_RESTRICTIONS);
     }
 
     @Test
@@ -206,13 +215,13 @@
         List<Rule> ruleList = new ArrayList();
         ruleList.add(negatedRule);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
         assertThat(result.get(PACKAGE_NAME_INDEXED)).isEmpty();
         assertThat(result.get(APP_CERTIFICATE_INDEXED)).isEmpty();
-        assertThat(result.get(NOT_INDEXED)).containsExactly(negatedRule);
+        assertThat(result.get(NOT_INDEXED).get("N/A")).containsExactly(negatedRule);
     }
 
     @Test
@@ -234,22 +243,36 @@
         ruleList.add(RULE_WITH_INSTALLER_RESTRICTIONS);
         ruleList.add(RULE_WITH_NONSTRING_RESTRICTIONS);
 
-        Map<Integer, List<Rule>> result = splitRulesIntoIndexBuckets(ruleList);
+        Map<Integer, TreeMap<String, List<Rule>>> result = splitRulesIntoIndexBuckets(ruleList);
 
         assertThat(result.keySet())
                 .containsExactly(NOT_INDEXED, PACKAGE_NAME_INDEXED, APP_CERTIFICATE_INDEXED);
 
         // We check asserts this way to ensure ordering based on package name.
-        assertThat(result.get(PACKAGE_NAME_INDEXED).get(0)).isEqualTo(packageNameRuleA);
-        assertThat(result.get(PACKAGE_NAME_INDEXED).get(1)).isEqualTo(packageNameRuleB);
-        assertThat(result.get(PACKAGE_NAME_INDEXED).get(2)).isEqualTo(packageNameRuleC);
+        assertThat(result.get(PACKAGE_NAME_INDEXED).keySet()).containsExactly("aaa", "bbb", "ccc");
+        Iterator<String> keySetIterator = result.get(PACKAGE_NAME_INDEXED).keySet().iterator();
+        assertThat(keySetIterator.next()).isEqualTo("aaa");
+        assertThat(keySetIterator.next()).isEqualTo("bbb");
+        assertThat(keySetIterator.next()).isEqualTo("ccc");
+        assertThat(result.get(PACKAGE_NAME_INDEXED).get("aaa")).containsExactly(packageNameRuleA);
+        assertThat(result.get(PACKAGE_NAME_INDEXED).get("bbb")).containsExactly(packageNameRuleB);
+        assertThat(result.get(PACKAGE_NAME_INDEXED).get("ccc")).containsExactly(packageNameRuleC);
 
         // We check asserts this way to ensure ordering based on app certificate.
-        assertThat(result.get(APP_CERTIFICATE_INDEXED).get(0)).isEqualTo(certificateRule1);
-        assertThat(result.get(APP_CERTIFICATE_INDEXED).get(1)).isEqualTo(certificateRule2);
-        assertThat(result.get(APP_CERTIFICATE_INDEXED).get(2)).isEqualTo(certificateRule3);
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).keySet()).containsExactly("cert1", "cert2",
+                "cert3");
+        keySetIterator = result.get(APP_CERTIFICATE_INDEXED).keySet().iterator();
+        assertThat(keySetIterator.next()).isEqualTo("cert1");
+        assertThat(keySetIterator.next()).isEqualTo("cert2");
+        assertThat(keySetIterator.next()).isEqualTo("cert3");
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert1")).containsExactly(
+                certificateRule1);
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert2")).containsExactly(
+                certificateRule2);
+        assertThat(result.get(APP_CERTIFICATE_INDEXED).get("cert3")).containsExactly(
+                certificateRule3);
 
-        assertThat(result.get(NOT_INDEXED))
+        assertThat(result.get(NOT_INDEXED).get("N/A"))
                 .containsExactly(
                         RULE_WITH_INSTALLER_RESTRICTIONS,
                         RULE_WITH_NONSTRING_RESTRICTIONS);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f9fc3a1..41416f1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -88,7 +88,6 @@
 import android.util.Log;
 import android.util.Pair;
 
-import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
@@ -114,6 +113,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
@@ -1241,7 +1241,7 @@
     protected void setCaller(String packageName, int userId) {
         mInjectedClientPackage = packageName;
         mInjectedCallingUid =
-                Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
+                Objects.requireNonNull(getInjectedPackageInfo(packageName, userId, false),
                         "Unknown package").applicationInfo.uid;
 
         // Set up LauncherApps for this caller.
diff --git a/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp
new file mode 100644
index 0000000..9aaa37d
--- /dev/null
+++ b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+android_test_helper_app {
+    name: "AppIntegrityManagerServiceTestApp",
+
+    test_suites: ["device-tests"],
+
+    certificate: "platform",
+}
diff --git a/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..f5dbf43
--- /dev/null
+++ b/services/tests/servicestests/test-apps/AppIntegrityManagerServiceTestApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.android.appintegritymanager.test.app"
+    android:versionCode="5000">
+
+    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="28" />
+
+    <application android:hasCode="false">
+        <meta-data android:name="allowed-installers" android:value="com.android.vending|play_store_cert,adb|"/>
+    </application>
+</manifest>
+
diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
new file mode 100644
index 0000000..b75510b
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.startop.iorap;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.server.wm.ActivityMetricsLaunchObserver;
+
+/**
+ * A validator to check the correctness of event sequence during app startup.
+ *
+ * <p> A valid state transition of event sequence is shown as the following:
+ *
+ * <pre>
+ *
+ *                                +--------------------+
+ *                                |                    |
+ *                                |        INIT        |
+ *                                |                    |
+ *                                +--------------------+
+ *                                          |
+ *                                          |
+ *                                          ↓
+ *                                +--------------------+
+ *                                |                    |
+ *            +-------------------|   INTENT_STARTED   | ←--------------------------------+
+ *            |                   |                    |                                  |
+ *            |                   +--------------------+                                  |
+ *            |                             |                                             |
+ *            |                             |                                             |
+ *            ↓                             ↓                                             |
+ * +--------------------+         +--------------------+                                  |
+ * |                    |         |                    |                                  |
+ * |   INTENT_FAILED    |         | ACTIVITY_LAUNCHED  |------------------+               |
+ * |                    |         |                    |                  |               |
+ * +--------------------+         +--------------------+                  |               |
+ *            |                              |                            |               |
+ *            |                              ↓                            ↓               |
+ *            |                   +--------------------+       +--------------------+     |
+ *            |                   |                    |       |                    |     |
+ *            +------------------ |  ACTIVITY_FINISHED |       | ACTIVITY_CANCELLED |     |
+ *            |                   |                    |       |                    |     |
+ *            |                   +--------------------+       +--------------------+     |
+ *            |                              |                            |               |
+ *            |                              |                            |               |
+ *            |                              ↓                            |               |
+ *            |                   +--------------------+                  |               |
+ *            |                   |                    |                  |               |
+ *            |                   | REPORT_FULLY_DRAWN |                  |               |
+ *            |                   |                    |                  |               |
+ *            |                   +--------------------+                  |               |
+ *            |                              |                            |               |
+ *            |                              |                            |               |
+ *            |                              ↓                            |               |
+ *            |                   +--------------------+                  |               |
+ *            |                   |                    |                  |               |
+ *            +-----------------→ |        END         |←-----------------+               |
+ *                                |                    |                                  |
+ *                                +--------------------+                                  |
+ *                                           |                                            |
+ *                                           |                                            |
+ *                                           |                                            |
+ *                                           +---------------------------------------------
+ *
+ * <p> END is not a real state in implementation. All states that points to END directly
+ * could transition to INTENT_STARTED.
+ *
+ * <p> If any bad transition happened, the state becomse UNKNOWN. The UNKNOWN state
+ * could be * accumulated, because during the UNKNOWN state more IntentStarted may
+ * be triggered. To recover from UNKNOWN to INIT, all the accumualted IntentStarted
+ * should termniate.
+ *
+ * <p> During UNKNOWN state, each IntentStarted increases the accumulation, and any of
+ * IntentFailed, ActivityLaunchCancelled and ActivityFinished decreases the accumulation.
+ * ReportFullyDrawn doesn't impact the accumulation.
+ */
+public class EventSequenceValidator implements ActivityMetricsLaunchObserver {
+  static final String TAG = "EventSequenceValidator";
+
+  private State state = State.INIT;
+  private long accIntentStartedEvents = 0;
+
+  @Override
+  public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "IntentStarted during UNKNOWN." + intent);
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    if (state != State.INIT &&
+        state != State.INTENT_FAILED &&
+        state != State.ACTIVITY_CANCELLED &&
+        state != State.ACTIVITY_FINISHED &&
+        state != State.REPORT_FULLY_DRAWN) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.INTENT_STARTED));
+      incAccIntentStartedEvents();
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_STARTED));
+    state = State.INTENT_STARTED;
+  }
+
+  @Override
+  public void onIntentFailed() {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "IntentFailed during UNKNOWN.");
+      decAccIntentStartedEvents();
+      return;
+    }
+    if (state != State.INTENT_STARTED) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.INTENT_FAILED));
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    Log.i(TAG, String.format("Tansition from %s to %s", state, State.INTENT_FAILED));
+    state = State.INTENT_FAILED;
+  }
+
+  @Override
+  public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
+      @Temperature int temperature) {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "onActivityLaunched during UNKNOWN.");
+      return;
+    }
+    if (state != State.INTENT_STARTED) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
+    state = State.ACTIVITY_LAUNCHED;
+  }
+
+  @Override
+  public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "onActivityLaunchCancelled during UNKNOWN.");
+      decAccIntentStartedEvents();
+      return;
+    }
+    if (state != State.ACTIVITY_LAUNCHED) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_CANCELLED));
+    state = State.ACTIVITY_CANCELLED;
+  }
+
+  @Override
+  public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
+      long timestampNs) {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "onActivityLaunchFinished during UNKNOWN.");
+      decAccIntentStartedEvents();
+      return;
+    }
+
+    if (state != State.ACTIVITY_LAUNCHED) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.ACTIVITY_FINISHED));
+      incAccIntentStartedEvents();
+      return;
+    }
+
+    Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_FINISHED));
+    state = State.ACTIVITY_FINISHED;
+  }
+
+  @Override
+  public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
+      long timestampNs) {
+    if (state == State.UNKNOWN) {
+      Log.e(TAG, "onReportFullyDrawn during UNKNOWN.");
+      return;
+    }
+    if (state == State.INIT) {
+      return;
+    }
+
+    if (state != State.ACTIVITY_FINISHED) {
+      Log.e(TAG,
+          String.format("Cannot transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+      return;
+    }
+
+    Log.i(TAG, String.format("Transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
+    state = State.REPORT_FULLY_DRAWN;
+  }
+
+  enum State {
+    INIT,
+    INTENT_STARTED,
+    INTENT_FAILED,
+    ACTIVITY_LAUNCHED,
+    ACTIVITY_CANCELLED,
+    ACTIVITY_FINISHED,
+    REPORT_FULLY_DRAWN,
+    UNKNOWN,
+  }
+
+  private void incAccIntentStartedEvents() {
+    if (accIntentStartedEvents < 0) {
+      throw new AssertionError(
+          String.format("The number of unknows cannot be negative"));
+    }
+    if (accIntentStartedEvents == 0) {
+      state = State.UNKNOWN;
+    }
+    ++accIntentStartedEvents;
+    Log.i(TAG,
+        String.format("inc AccIntentStartedEvents to %d", accIntentStartedEvents));
+  }
+
+  private void decAccIntentStartedEvents() {
+    if (accIntentStartedEvents <= 0) {
+      throw new AssertionError(
+          String.format("The number of unknows cannot be negative"));
+    }
+    if(accIntentStartedEvents == 1) {
+      state = State.INIT;
+    }
+    --accIntentStartedEvents;
+    Log.i(TAG,
+        String.format("dec AccIntentStartedEvents to %d", accIntentStartedEvents));
+  }
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index f753548..badff7b 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -283,6 +283,7 @@
     }
 
     private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
+    private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
     private boolean mRegisteredListeners = false;
 
     private void registerInProcessListenersLocked() {
@@ -303,6 +304,7 @@
         ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
                 provideLaunchObserverRegistry();
         launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
+        launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
 
         mRegisteredListeners = true;
     }
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 0659665..9e6dfef 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -98,7 +98,13 @@
             TelephonyManager.NETWORK_TYPE_GSM,
             TelephonyManager.NETWORK_TYPE_TD_SCDMA,
             TelephonyManager.NETWORK_TYPE_IWLAN,
-            TelephonyManager.NETWORK_TYPE_LTE_CA,
+
+            //TODO: In order for @SystemApi methods to use this class, there cannot be any
+            // public hidden members.  This network type is marked as hidden because it is not a
+            // true network type and we are looking to remove it completely from the available list
+            // of network types.
+            //TelephonyManager.NETWORK_TYPE_LTE_CA,
+
             TelephonyManager.NETWORK_TYPE_NR,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -590,4 +596,17 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface ImsAudioCodec {
     }
+
+    /**
+     * UICC SIM Application Types
+     */
+    @IntDef(prefix = { "APPTYPE_" }, value = {
+            TelephonyManager.APPTYPE_SIM,
+            TelephonyManager.APPTYPE_USIM,
+            TelephonyManager.APPTYPE_RUIM,
+            TelephonyManager.APPTYPE_CSIM,
+            TelephonyManager.APPTYPE_ISIM
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface UiccAppType{}
 }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ab51d8a..0a6183c 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1950,9 +1950,18 @@
      * Returns a copy of self with location-identifying information removed.
      * Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
      * is true, clears other info as well.
+     *
+     * @param removeCoarseLocation Whether to also remove coarse location information.
+     *                             if false, it only clears fine location information such as
+     *                             NetworkRegistrationInfo's CellIdentity fields; If true, it will
+     *                             also remove other location information such as operator's MCC
+     *                             and MNC.
+     * @return the copied ServiceState with location info sanitized.
      * @hide
      */
-    public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+    @SystemApi
+    @NonNull
+    public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
         ServiceState state = new ServiceState(this);
         synchronized (state.mNetworkRegistrationInfos) {
             List<NetworkRegistrationInfo> networkRegistrationInfos =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 365ab22..deafbb3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -73,6 +73,7 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.UiccAppType;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import android.telephony.data.ApnSetting.MvnoType;
 import android.telephony.emergency.EmergencyNumber;
@@ -6781,19 +6782,6 @@
         }
     }
 
-    /**
-     * UICC SIM Application Types
-     * @hide
-     */
-    @IntDef(prefix = { "APPTYPE_" }, value = {
-            APPTYPE_SIM,
-            APPTYPE_USIM,
-            APPTYPE_RUIM,
-            APPTYPE_CSIM,
-            APPTYPE_ISIM
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface UiccAppType{}
     /** UICC application type is SIM */
     public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
     /** UICC application type is USIM */
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index daa85bd..f6699fa 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -31,6 +31,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
 import android.os.UserManager;
@@ -1122,4 +1123,39 @@
             InstallUtils.dropShellPermissionIdentity();
         }
     }
+
+    @Test
+    public void testRollbackDataPolicy() throws Exception {
+        try {
+            InstallUtils.adoptShellPermissionIdentity(
+                    Manifest.permission.INSTALL_PACKAGES,
+                    Manifest.permission.DELETE_PACKAGES,
+                    Manifest.permission.TEST_MANAGE_ROLLBACKS);
+
+            Uninstall.packages(TestApp.A, TestApp.B);
+            Install.multi(TestApp.A1, TestApp.B1).commit();
+            // Write user data version = 1
+            InstallUtils.processUserData(TestApp.A);
+            InstallUtils.processUserData(TestApp.B);
+
+            Install a2 = Install.single(TestApp.A2)
+                    .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+            Install b2 = Install.single(TestApp.B2)
+                    .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+            Install.multi(a2, b2).setEnableRollback().commit();
+            // Write user data version = 2
+            InstallUtils.processUserData(TestApp.A);
+            InstallUtils.processUserData(TestApp.B);
+
+            RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+            RollbackUtils.rollback(info.getRollbackId());
+            // Read user data version from userdata.txt
+            // A's user data version is -1 for user data is wiped.
+            // B's user data version is 1 as rollback committed.
+            assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+            assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+        } finally {
+            InstallUtils.dropShellPermissionIdentity();
+        }
+    }
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index bb3906d..40169b8 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -384,6 +384,44 @@
         RollbackUtils.getRollbackManager().expireRollbackForPackage(getModuleMetadataPackageName());
     }
 
+    @Test
+    public void testRollbackDataPolicy_Phase1() throws Exception {
+        Uninstall.packages(TestApp.A, TestApp.B);
+        Install.multi(TestApp.A1, TestApp.B1).commit();
+        // Write user data version = 1
+        InstallUtils.processUserData(TestApp.A);
+        InstallUtils.processUserData(TestApp.B);
+
+        Install a2 = Install.single(TestApp.A2).setStaged()
+                .setEnableRollback(PackageManager.RollbackDataPolicy.WIPE);
+        Install b2 = Install.single(TestApp.B2).setStaged()
+                .setEnableRollback(PackageManager.RollbackDataPolicy.RESTORE);
+        Install.multi(a2, b2).setEnableRollback().setStaged().commit();
+    }
+
+    @Test
+    public void testRollbackDataPolicy_Phase2() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2);
+        // Write user data version = 2
+        InstallUtils.processUserData(TestApp.A);
+        InstallUtils.processUserData(TestApp.B);
+
+        RollbackInfo info = RollbackUtils.getAvailableRollback(TestApp.A);
+        RollbackUtils.rollback(info.getRollbackId());
+    }
+
+    @Test
+    public void testRollbackDataPolicy_Phase3() throws Exception {
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+        assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1);
+        // Read user data version from userdata.txt
+        // A's user data version is -1 for user data is wiped.
+        // B's user data version is 1 as rollback committed.
+        assertThat(InstallUtils.getUserDataVersion(TestApp.A)).isEqualTo(-1);
+        assertThat(InstallUtils.getUserDataVersion(TestApp.B)).isEqualTo(1);
+    }
+
     private static void runShellCommand(String cmd) {
         ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
                 .executeShellCommand(cmd);
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 8ab4c4c..4644d8a 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -192,6 +192,15 @@
         }
     }
 
+    @Test
+    public void testRollbackDataPolicy() throws Exception {
+        runPhase("testRollbackDataPolicy_Phase1");
+        getDevice().reboot();
+        runPhase("testRollbackDataPolicy_Phase2");
+        getDevice().reboot();
+        runPhase("testRollbackDataPolicy_Phase3");
+    }
+
     private void crashProcess(String processName, int numberOfCrashes) throws Exception {
         String pid = "";
         String lastPid = "invalid";
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 15c3278..d3958a6 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -25,6 +25,8 @@
         "java_writer.cpp",
         "java_writer_q.cpp",
         "main.cpp",
+        "native_writer.cpp",
+        "native_writer_q.cpp",
         "utils.cpp",
     ],
     cflags: [
@@ -121,17 +123,5 @@
         "libcutils",
     ],
     static_libs: ["libstatssocket"],
-    target: {
-        android: {
-            shared_libs: [
-                "libutils",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libutils",
-            ],
-        },
-    },
 }
 
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index fa55601..0b82a3d 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -405,9 +405,9 @@
         atomDecl.whitelisted = true;
     }
 
-    if (atomField->options().HasExtension(os::statsd::log_from_module)) {
+    if (atomField->options().HasExtension(os::statsd::module)) {
         atomDecl.hasModule = true;
-        atomDecl.moduleName = atomField->options().GetExtension(os::statsd::log_from_module);
+        atomDecl.moduleName = atomField->options().GetExtension(os::statsd::module);
     }
 
     vector<java_type_t> signature;
diff --git a/tools/stats_log_api_gen/atoms_info_writer.h b/tools/stats_log_api_gen/atoms_info_writer.h
index bc67782..12ac862 100644
--- a/tools/stats_log_api_gen/atoms_info_writer.h
+++ b/tools/stats_log_api_gen/atoms_info_writer.h
@@ -27,8 +27,7 @@
 using namespace std;
 
 int write_atoms_info_cpp(FILE* out, const Atoms& atoms, const string& namespaceStr,
-        const string& importHeader, const string& statslogHeader
-);
+        const string& importHeader, const string& statslogHeader);
 
 int write_atoms_info_header(FILE* out, const Atoms& atoms, const string& namespaceStr);
 
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 712b48e..7f0872c 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -48,7 +48,8 @@
         FILE* out,
         const map<vector<java_type_t>, set<string>>& signatures_to_modules,
         const AtomDecl &attributionDecl,
-        const string& moduleName
+        const string& moduleName,
+        const bool supportQ
         ) {
     for (auto signature_to_modules_it = signatures_to_modules.begin();
             signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
@@ -82,8 +83,10 @@
 
         // Print method body.
         string indent("");
-        if (DEFAULT_MODULE_NAME != moduleName) {
-            fprintf(out, "        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
+        if (supportQ) {
+            // TODO(b/146235828): Use just SDK_INT check once it is incremented from Q.
+            fprintf(out, "        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ||\n");
+            fprintf(out, "                Build.VERSION.CODENAME.equals(\"R\")) {\n");
             indent = "    ";
         }
 
@@ -193,7 +196,7 @@
         fprintf(out, "%s        StatsLog.write(builder.build());\n", indent.c_str());
 
         // Add support for writing using Q schema if this is not the default module.
-        if (DEFAULT_MODULE_NAME != moduleName) {
+        if (supportQ) {
             fprintf(out, "        } else {\n");
             fprintf(out, "            QLogger.write(code");
             argIndex = 1;
@@ -225,15 +228,17 @@
 
 int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
                                     const string& moduleName, const string& javaClass,
-                                    const string& javaPackage) {
+                                    const string& javaPackage, const bool supportQ) {
     // Print prelude
     fprintf(out, "// This file is autogenerated\n");
     fprintf(out, "\n");
     fprintf(out, "package %s;\n", javaPackage.c_str());
     fprintf(out, "\n");
     fprintf(out, "\n");
-    fprintf(out, "import android.os.Build;\n");
-    fprintf(out, "import android.os.SystemClock;\n");
+    if (supportQ) {
+        fprintf(out, "import android.os.Build;\n");
+        fprintf(out, "import android.os.SystemClock;\n");
+    }
 
     if (DEFAULT_MODULE_NAME == moduleName) {
         // Mainline modules don't use WorkSource logging.
@@ -271,12 +276,15 @@
 
     // Print write methods.
     fprintf(out, "    // Write methods\n");
-    errors += write_java_methods(out, atoms.signatures_to_modules, attributionDecl, moduleName);
+    errors += write_java_methods(
+            out, atoms.signatures_to_modules, attributionDecl, moduleName, supportQ);
     errors += write_java_non_chained_methods(
             out, atoms.non_chained_signatures_to_modules, moduleName);
     if (DEFAULT_MODULE_NAME == moduleName) {
         errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
-    } else {
+    }
+
+    if (supportQ) {
         errors += write_java_q_logger_class(
                 out, atoms.signatures_to_modules, attributionDecl, moduleName);
     }
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
index 031266b..9324b23 100644
--- a/tools/stats_log_api_gen/java_writer.h
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -32,8 +32,7 @@
 
 int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
                                     const string& moduleName, const string& javaClass,
-                                    const string& javaPackage
-);
+                                    const string& javaPackage, const bool supportQ);
 
 }  // namespace stats_log_api_gen
 }  // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index c8f4ccf..96ac745 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -37,22 +37,20 @@
         const map<vector<java_type_t>, set<string>>& signatures_to_modules,
         const AtomDecl &attributionDecl,
         const string& moduleName,
-        const string& indent
-);
+        const string& indent);
 
 void write_java_helpers_for_q_schema_methods(
         FILE * out,
         const AtomDecl &attributionDecl,
         const int requiredHelpers,
-        const string& indent
-);
+        const string& indent);
 
 #if defined(STATS_SCHEMA_LEGACY)
 int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);
 
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
-                                    const string& moduleName, const string& javaClass,
-                                    const string& javaPackage);
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
+        const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass,
+        const string& javaPackage);
 #endif
 }  // namespace stats_log_api_gen
 }  // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index ad171da..00a3704 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -6,6 +6,7 @@
 #include "java_writer.h"
 #endif
 #include "java_writer_q.h"
+#include "native_writer.h"
 #include "utils.h"
 
 #include "frameworks/base/cmds/statsd/src/atoms.pb.h"
@@ -27,496 +28,6 @@
 
 using android::os::statsd::Atom;
 
-static int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
-                               const string& moduleName, const string& cppNamespace,
-                               const string& importHeader) {
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-
-    fprintf(out, "#include <mutex>\n");
-    fprintf(out, "#include <chrono>\n");
-    fprintf(out, "#include <thread>\n");
-    fprintf(out, "#ifdef __ANDROID__\n");
-    fprintf(out, "#include <cutils/properties.h>\n");
-    fprintf(out, "#endif\n");
-    fprintf(out, "#include <stats_event_list.h>\n");
-    fprintf(out, "#include <log/log.h>\n");
-    fprintf(out, "#include <%s>\n", importHeader.c_str());
-    fprintf(out, "#include <utils/SystemClock.h>\n");
-    fprintf(out, "\n");
-
-    write_namespace(out, cppNamespace);
-    fprintf(out, "// the single event tag id for all stats logs\n");
-    fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
-    fprintf(out, "#ifdef __ANDROID__\n");
-    fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
-    fprintf(out, "#else\n");
-    fprintf(out, "const static bool kStatsdEnabled = false;\n");
-    fprintf(out, "#endif\n");
-
-    fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
-    fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
-    fprintf(out, "static std::mutex mLogdRetryMutex;\n");
-
-    // Print write methods
-    fprintf(out, "\n");
-    for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
-        signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
-        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
-            continue;
-        }
-        vector<java_type_t> signature = signature_to_modules_it->first;
-        int argIndex;
-
-        fprintf(out, "int\n");
-        fprintf(out, "try_stats_write(int32_t code");
-        argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin();
-            arg != signature.end(); arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                for (auto chainField : attributionDecl.fields) {
-                    if (chainField.javaType == JAVA_TYPE_STRING) {
-                            fprintf(out, ", const std::vector<%s>& %s",
-                                 cpp_type_name(chainField.javaType),
-                                 chainField.name.c_str());
-                    } else {
-                            fprintf(out, ", const %s* %s, size_t %s_length",
-                                 cpp_type_name(chainField.javaType),
-                                 chainField.name.c_str(), chainField.name.c_str());
-                    }
-                }
-            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
-                             "const std::map<int, int64_t>& arg%d_2, "
-                             "const std::map<int, char const*>& arg%d_3, "
-                             "const std::map<int, float>& arg%d_4",
-                             argIndex, argIndex, argIndex, argIndex);
-            } else {
-                fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ")\n");
-
-        fprintf(out, "{\n");
-        argIndex = 1;
-        fprintf(out, "  if (kStatsdEnabled) {\n");
-        fprintf(out, "    stats_event_list event(kStatsEventTag);\n");
-        fprintf(out, "    event << android::elapsedRealtimeNano();\n\n");
-        fprintf(out, "    event << code;\n\n");
-        for (vector<java_type_t>::const_iterator arg = signature.begin();
-            arg != signature.end(); arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                for (const auto &chainField : attributionDecl.fields) {
-                    if (chainField.javaType == JAVA_TYPE_STRING) {
-                        fprintf(out, "    if (%s_length != %s.size()) {\n",
-                            attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
-                        fprintf(out, "        return -EINVAL;\n");
-                        fprintf(out, "    }\n");
-                    }
-                }
-                fprintf(out, "\n    event.begin();\n");
-                fprintf(out, "    for (size_t i = 0; i < %s_length; ++i) {\n",
-                    attributionDecl.fields.front().name.c_str());
-                fprintf(out, "        event.begin();\n");
-                for (const auto &chainField : attributionDecl.fields) {
-                    if (chainField.javaType == JAVA_TYPE_STRING) {
-                        fprintf(out, "        if (%s[i] != NULL) {\n", chainField.name.c_str());
-                        fprintf(out, "           event << %s[i];\n", chainField.name.c_str());
-                        fprintf(out, "        } else {\n");
-                        fprintf(out, "           event << \"\";\n");
-                        fprintf(out, "        }\n");
-                    } else {
-                        fprintf(out, "        event << %s[i];\n", chainField.name.c_str());
-                    }
-                }
-                fprintf(out, "        event.end();\n");
-                fprintf(out, "    }\n");
-                fprintf(out, "    event.end();\n\n");
-            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                    fprintf(out, "    event.begin();\n\n");
-                    fprintf(out, "    for (const auto& it : arg%d_1) {\n", argIndex);
-                    fprintf(out, "         event.begin();\n");
-                    fprintf(out, "         event << it.first;\n");
-                    fprintf(out, "         event << it.second;\n");
-                    fprintf(out, "         event.end();\n");
-                    fprintf(out, "    }\n");
-
-                    fprintf(out, "    for (const auto& it : arg%d_2) {\n", argIndex);
-                    fprintf(out, "         event.begin();\n");
-                    fprintf(out, "         event << it.first;\n");
-                    fprintf(out, "         event << it.second;\n");
-                    fprintf(out, "         event.end();\n");
-                    fprintf(out, "    }\n");
-
-                    fprintf(out, "    for (const auto& it : arg%d_3) {\n", argIndex);
-                    fprintf(out, "         event.begin();\n");
-                    fprintf(out, "         event << it.first;\n");
-                    fprintf(out, "         event << it.second;\n");
-                    fprintf(out, "         event.end();\n");
-                    fprintf(out, "    }\n");
-
-                    fprintf(out, "    for (const auto& it : arg%d_4) {\n", argIndex);
-                    fprintf(out, "         event.begin();\n");
-                    fprintf(out, "         event << it.first;\n");
-                    fprintf(out, "         event << it.second;\n");
-                    fprintf(out, "         event.end();\n");
-                    fprintf(out, "    }\n");
-
-                    fprintf(out, "    event.end();\n\n");
-            } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
-                fprintf(out,
-                        "    event.AppendCharArray(arg%d.arg, "
-                        "arg%d.arg_length);\n",
-                        argIndex, argIndex);
-            } else {
-                if (*arg == JAVA_TYPE_STRING) {
-                    fprintf(out, "    if (arg%d == NULL) {\n", argIndex);
-                    fprintf(out, "        arg%d = \"\";\n", argIndex);
-                    fprintf(out, "    }\n");
-                }
-                fprintf(out, "    event << arg%d;\n", argIndex);
-            }
-            argIndex++;
-        }
-
-        fprintf(out, "    return event.write(LOG_ID_STATS);\n");
-        fprintf(out, "  } else {\n");
-        fprintf(out, "    return 1;\n");
-        fprintf(out, "  }\n");
-        fprintf(out, "}\n");
-        fprintf(out, "\n");
-    }
-
-   for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
-       signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
-       if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
-           continue;
-       }
-       vector<java_type_t> signature = signature_to_modules_it->first;
-       int argIndex;
-
-       fprintf(out, "int\n");
-       fprintf(out, "stats_write(int32_t code");
-       argIndex = 1;
-       for (vector<java_type_t>::const_iterator arg = signature.begin();
-           arg != signature.end(); arg++) {
-           if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-               for (auto chainField : attributionDecl.fields) {
-                   if (chainField.javaType == JAVA_TYPE_STRING) {
-                           fprintf(out, ", const std::vector<%s>& %s",
-                                cpp_type_name(chainField.javaType),
-                                chainField.name.c_str());
-                   } else {
-                           fprintf(out, ", const %s* %s, size_t %s_length",
-                                cpp_type_name(chainField.javaType),
-                                chainField.name.c_str(), chainField.name.c_str());
-                   }
-               }
-           } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-               fprintf(out,
-                       ", const std::map<int, int32_t>& arg%d_1, "
-                       "const std::map<int, int64_t>& arg%d_2, "
-                       "const std::map<int, char const*>& arg%d_3, "
-                       "const std::map<int, float>& arg%d_4",
-                       argIndex, argIndex, argIndex, argIndex);
-           } else {
-               fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-           }
-           argIndex++;
-       }
-       fprintf(out, ")\n");
-
-       fprintf(out, "{\n");
-       fprintf(out, "  int ret = 0;\n");
-
-       fprintf(out, "  for(int retry = 0; retry < 2; ++retry) {\n");
-       fprintf(out, "      ret =  try_stats_write(code");
-
-       argIndex = 1;
-       for (vector<java_type_t>::const_iterator arg = signature.begin();
-           arg != signature.end(); arg++) {
-           if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-               for (auto chainField : attributionDecl.fields) {
-                   if (chainField.javaType == JAVA_TYPE_STRING) {
-                           fprintf(out, ", %s",
-                                chainField.name.c_str());
-                   } else {
-                           fprintf(out, ",  %s,  %s_length",
-                                chainField.name.c_str(), chainField.name.c_str());
-                   }
-               }
-           } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-               fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
-                       argIndex, argIndex, argIndex);
-           } else {
-               fprintf(out, ", arg%d", argIndex);
-           }
-           argIndex++;
-       }
-       fprintf(out, ");\n");
-       fprintf(out, "      if (ret >= 0) { break; }\n");
-
-       fprintf(out, "      {\n");
-       fprintf(out, "          std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
-       fprintf(out, "          if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
-                                "kMinRetryIntervalNs) break;\n");
-       fprintf(out, "          lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
-       fprintf(out, "      }\n");
-       fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
-       fprintf(out, "  }\n");
-       fprintf(out, "  if (ret < 0) {\n");
-       fprintf(out, "      note_log_drop(ret, code);\n");
-       fprintf(out, "  }\n");
-       fprintf(out, "  return ret;\n");
-       fprintf(out, "}\n");
-       fprintf(out, "\n");
-   }
-
-    for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
-            signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
-        if (!signature_needed_for_module(signature_it->second, moduleName)) {
-            continue;
-        }
-        vector<java_type_t> signature = signature_it->first;
-        int argIndex;
-
-        fprintf(out, "int\n");
-        fprintf(out, "try_stats_write_non_chained(int32_t code");
-        argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin();
-            arg != signature.end(); arg++) {
-            fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-            argIndex++;
-        }
-        fprintf(out, ")\n");
-
-        fprintf(out, "{\n");
-        argIndex = 1;
-        fprintf(out, "  if (kStatsdEnabled) {\n");
-        fprintf(out, "    stats_event_list event(kStatsEventTag);\n");
-        fprintf(out, "    event << android::elapsedRealtimeNano();\n\n");
-        fprintf(out, "    event << code;\n\n");
-        for (vector<java_type_t>::const_iterator arg = signature.begin();
-            arg != signature.end(); arg++) {
-            if (argIndex == 1) {
-                fprintf(out, "    event.begin();\n\n");
-                fprintf(out, "    event.begin();\n");
-            }
-            if (*arg == JAVA_TYPE_STRING) {
-                fprintf(out, "    if (arg%d == NULL) {\n", argIndex);
-                fprintf(out, "        arg%d = \"\";\n", argIndex);
-                fprintf(out, "    }\n");
-            }
-            if (*arg == JAVA_TYPE_BYTE_ARRAY) {
-                fprintf(out,
-                        "    event.AppendCharArray(arg%d.arg, "
-                        "arg%d.arg_length);",
-                        argIndex, argIndex);
-            } else {
-                fprintf(out, "    event << arg%d;\n", argIndex);
-            }
-            if (argIndex == 2) {
-                fprintf(out, "    event.end();\n\n");
-                fprintf(out, "    event.end();\n\n");
-            }
-            argIndex++;
-        }
-
-        fprintf(out, "    return event.write(LOG_ID_STATS);\n");
-        fprintf(out, "  } else {\n");
-        fprintf(out, "    return 1;\n");
-        fprintf(out, "  }\n");
-        fprintf(out, "}\n");
-        fprintf(out, "\n");
-    }
-
-    for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
-            signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
-       if (!signature_needed_for_module(signature_it->second, moduleName)) {
-           continue;
-       }
-       vector<java_type_t> signature = signature_it->first;
-       int argIndex;
-
-       fprintf(out, "int\n");
-       fprintf(out, "stats_write_non_chained(int32_t code");
-       argIndex = 1;
-       for (vector<java_type_t>::const_iterator arg = signature.begin();
-           arg != signature.end(); arg++) {
-           fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-           argIndex++;
-       }
-       fprintf(out, ")\n");
-
-       fprintf(out, "{\n");
-
-       fprintf(out, "  int ret = 0;\n");
-       fprintf(out, "  for(int retry = 0; retry < 2; ++retry) {\n");
-       fprintf(out, "      ret =  try_stats_write_non_chained(code");
-
-       argIndex = 1;
-       for (vector<java_type_t>::const_iterator arg = signature.begin();
-           arg != signature.end(); arg++) {
-           fprintf(out, ", arg%d",   argIndex);
-           argIndex++;
-       }
-       fprintf(out, ");\n");
-       fprintf(out, "      if (ret >= 0) { break; }\n");
-
-       fprintf(out, "      {\n");
-       fprintf(out, "          std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n");
-       fprintf(out, "          if ((android::elapsedRealtimeNano() - lastRetryTimestampNs) <= "
-                                "kMinRetryIntervalNs) break;\n");
-       fprintf(out, "          lastRetryTimestampNs = android::elapsedRealtimeNano();\n");
-       fprintf(out, "      }\n");
-
-       fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
-       fprintf(out, "  }\n");
-       fprintf(out, "  if (ret < 0) {\n");
-       fprintf(out, "      note_log_drop(ret, code);\n");
-       fprintf(out, "  }\n");
-       fprintf(out, "  return ret;\n\n");
-       fprintf(out, "}\n");
-
-       fprintf(out, "\n");
-   }
-
-
-    // Print footer
-    fprintf(out, "\n");
-    write_closing_namespace(out, cppNamespace);
-
-    return 0;
-}
-
-static void write_cpp_method_header(
-        FILE* out,
-        const string& method_name,
-        const map<vector<java_type_t>, set<string>>& signatures_to_modules,
-        const AtomDecl &attributionDecl, const string& moduleName) {
-
-    for (auto signature_to_modules_it = signatures_to_modules.begin();
-            signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
-        // Skip if this signature is not needed for the module.
-        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
-            continue;
-        }
-
-        vector<java_type_t> signature = signature_to_modules_it->first;
-        fprintf(out, "int %s(int32_t code", method_name.c_str());
-        int argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin();
-                arg != signature.end(); arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                for (auto chainField : attributionDecl.fields) {
-                    if (chainField.javaType == JAVA_TYPE_STRING) {
-                        fprintf(out, ", const std::vector<%s>& %s",
-                            cpp_type_name(chainField.javaType), chainField.name.c_str());
-                    } else {
-                        fprintf(out, ", const %s* %s, size_t %s_length",
-                            cpp_type_name(chainField.javaType),
-                            chainField.name.c_str(), chainField.name.c_str());
-                    }
-                }
-            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
-                             "const std::map<int, int64_t>& arg%d_2, "
-                             "const std::map<int, char const*>& arg%d_3, "
-                             "const std::map<int, float>& arg%d_4",
-                             argIndex, argIndex, argIndex, argIndex);
-            } else {
-                fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ");\n");
-
-    }
-}
-
-static int
-write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
-        const string& moduleName, const string& cppNamespace)
-{
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-    fprintf(out, "#pragma once\n");
-    fprintf(out, "\n");
-    fprintf(out, "#include <stdint.h>\n");
-    fprintf(out, "#include <vector>\n");
-    fprintf(out, "#include <map>\n");
-    fprintf(out, "#include <set>\n");
-    fprintf(out, "\n");
-
-    write_namespace(out, cppNamespace);
-    fprintf(out, "\n");
-    fprintf(out, "/*\n");
-    fprintf(out, " * API For logging statistics events.\n");
-    fprintf(out, " */\n");
-    fprintf(out, "\n");
-
-    write_native_atom_constants(out, atoms, attributionDecl, moduleName);
-
-    // Print constants for the enum values.
-    fprintf(out, "//\n");
-    fprintf(out, "// Constants for enum values\n");
-    fprintf(out, "//\n\n");
-    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
-        atom != atoms.decls.end(); atom++) {
-        // Skip if the atom is not needed for the module.
-        if (!atom_needed_for_module(*atom, moduleName)) {
-            continue;
-        }
-
-        for (vector<AtomField>::const_iterator field = atom->fields.begin();
-            field != atom->fields.end(); field++) {
-            if (field->javaType == JAVA_TYPE_ENUM) {
-                fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
-                    field->name.c_str());
-                for (map<int, string>::const_iterator value = field->enumValues.begin();
-                    value != field->enumValues.end(); value++) {
-                    fprintf(out, "const int32_t %s__%s__%s = %d;\n",
-                        make_constant_name(atom->message).c_str(),
-                        make_constant_name(field->name).c_str(),
-                        make_constant_name(value->second).c_str(),
-                        value->first);
-                }
-                fprintf(out, "\n");
-            }
-        }
-    }
-
-    fprintf(out, "struct BytesField {\n");
-    fprintf(out,
-            "  BytesField(char const* array, size_t len) : arg(array), "
-            "arg_length(len) {}\n");
-    fprintf(out, "  char const* arg;\n");
-    fprintf(out, "  size_t arg_length;\n");
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-
-    // Print write methods
-    fprintf(out, "//\n");
-    fprintf(out, "// Write methods\n");
-    fprintf(out, "//\n");
-    write_cpp_method_header(out, "stats_write", atoms.signatures_to_modules, attributionDecl,
-            moduleName);
-
-    fprintf(out, "//\n");
-    fprintf(out, "// Write flattened methods\n");
-    fprintf(out, "//\n");
-    write_cpp_method_header(out, "stats_write_non_chained", atoms.non_chained_signatures_to_modules,
-        attributionDecl, moduleName);
-
-    fprintf(out, "\n");
-    write_closing_namespace(out, cppNamespace);
-
-    return 0;
-}
-
 // Hide the JNI write helpers that are not used in the new schema.
 // TODO(b/145100015): Remove this and other JNI related functionality once StatsEvent migration is
 // complete.
@@ -999,7 +510,9 @@
     fprintf(stderr, "                                    required for java with module\n");
     fprintf(stderr, "  --javaClass CLASS    the class name of the java class.\n");
     fprintf(stderr, "                       Optional for Java with module.\n");
-    fprintf(stderr, "                       Default is \"StatsLogInternal\"\n");}
+    fprintf(stderr, "                       Default is \"StatsLogInternal\"\n");
+    fprintf(stderr, "  --supportQ           Include support for Android Q.\n");
+}
 
 /**
  * Do the argument parsing and execute the tasks.
@@ -1020,6 +533,7 @@
     string atomsInfoCppHeaderImport = DEFAULT_ATOMS_INFO_CPP_HEADER_IMPORT;
     string javaPackage = DEFAULT_JAVA_PACKAGE;
     string javaClass = DEFAULT_JAVA_CLASS;
+    bool supportQ = false;
 
     int index = 1;
     while (index < argc) {
@@ -1110,6 +624,8 @@
                 return 1;
             }
             atomsInfoCppHeaderImport = argv[index];
+        } else if (0 == strcmp("--supportQ", argv[index])) {
+            supportQ = true;
         }
 
         index++;
@@ -1125,6 +641,12 @@
         return 1;
     }
 
+    if (DEFAULT_MODULE_NAME == moduleName && supportQ) {
+        // Support for Q schema is not needed for default module.
+        fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
+        return 1;
+    }
+
     // Collate the parameters
     Atoms atoms;
     int errorCount = collate_atoms(Atom::descriptor(), &atoms);
@@ -1179,7 +701,7 @@
             return 1;
         }
         errorCount = android::stats_log_api_gen::write_stats_log_cpp(
-            out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport);
+            out, atoms, attributionDecl, moduleName, cppNamespace, cppHeaderImport, supportQ);
         fclose(out);
     }
 
@@ -1227,7 +749,7 @@
             javaPackage = "android.util";
         }
         errorCount = android::stats_log_api_gen::write_stats_log_java(
-                out, atoms, attributionDecl, moduleName, javaClass, javaPackage);
+                out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
 #endif
 
         fclose(out);
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
new file mode 100644
index 0000000..c7a34fe
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -0,0 +1,342 @@
+/*
+ * 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.
+ */
+
+#include "native_writer.h"
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+#if !defined(STATS_SCHEMA_LEGACY)
+static void write_native_key_value_pairs_for_type(FILE* out, const int argIndex,
+        const int typeIndex, const string& type, const string& valueFieldName) {
+    fprintf(out, "    for (const auto& it : arg%d_%d) {\n", argIndex, typeIndex);
+    fprintf(out, "        pairs.push_back("
+            "{ .key = it.first, .valueType = %s, .%s = it.second });\n",
+            type.c_str(), valueFieldName.c_str());
+    fprintf(out, "    }\n");
+
+}
+
+static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName, const bool supportQ) {
+    fprintf(out, "\n");
+    for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+        signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_to_modules_it->first;
+
+        write_native_method_signature(out, "int stats_write", signature,
+                attributionDecl, " {");
+
+        int argIndex = 1;
+        if (supportQ) {
+            fprintf(out, "    StatsEventCompat event;\n");
+            fprintf(out, "    event.setAtomId(code);\n");
+            for (vector<java_type_t>::const_iterator arg = signature.begin();
+                    arg != signature.end(); arg++) {
+                switch (*arg) {
+                    case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+                        const char* uidName = attributionDecl.fields.front().name.c_str();
+                        const char* tagName = attributionDecl.fields.back().name.c_str();
+                        fprintf(out, "    event.writeAttributionChain(%s, %s_length, %s);\n",
+                                uidName, uidName, tagName);
+                        break;
+                    }
+                    case JAVA_TYPE_KEY_VALUE_PAIR:
+                        fprintf(out, "    event.writeKeyValuePairs("
+                                "arg%d_1, arg%d_2, arg%d_3, arg%d_4);\n",
+                                argIndex, argIndex, argIndex, argIndex);
+                        break;
+                    case JAVA_TYPE_BYTE_ARRAY:
+                        fprintf(out, "    event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
+                                argIndex, argIndex);
+                        break;
+                    case JAVA_TYPE_BOOLEAN:
+                        fprintf(out, "    event.writeBool(arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_INT: // Fall through.
+                    case JAVA_TYPE_ENUM:
+                        fprintf(out, "    event.writeInt32(arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_FLOAT:
+                        fprintf(out, "    event.writeFloat(arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_LONG:
+                        fprintf(out, "    event.writeInt64(arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_STRING:
+                        fprintf(out, "    event.writeString(arg%d);\n", argIndex);
+                        break;
+                    default:
+                        // Unsupported types: OBJECT, DOUBLE.
+                        fprintf(stderr, "Encountered unsupported type.");
+                        return 1;
+                }
+                argIndex++;
+            }
+            fprintf(out, "    return event.writeToSocket();\n");
+        } else {
+            fprintf(out, "    struct stats_event* event = stats_event_obtain();\n");
+            fprintf(out, "    stats_event_set_atom_id(event, code);\n");
+            for (vector<java_type_t>::const_iterator arg = signature.begin();
+                    arg != signature.end(); arg++) {
+                switch (*arg) {
+                    case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+                        const char* uidName = attributionDecl.fields.front().name.c_str();
+                        const char* tagName = attributionDecl.fields.back().name.c_str();
+                        fprintf(out,
+                                "    stats_event_write_attribution_chain(event, "
+                                "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
+                                "static_cast<uint8_t>(%s_length));\n",
+                                uidName, tagName, uidName);
+                        break;
+                    }
+                    case JAVA_TYPE_KEY_VALUE_PAIR:
+                        fprintf(out, "    std::vector<key_value_pair> pairs;\n");
+                        write_native_key_value_pairs_for_type(
+                                out, argIndex, 1, "INT32_TYPE", "int32Value");
+                        write_native_key_value_pairs_for_type(
+                                out, argIndex, 2, "INT64_TYPE", "int64Value");
+                        write_native_key_value_pairs_for_type(
+                                out, argIndex, 3, "STRING_TYPE", "stringValue");
+                        write_native_key_value_pairs_for_type(
+                                out, argIndex, 4, "FLOAT_TYPE", "floatValue");
+                        fprintf(out,
+                                "    stats_event_write_key_value_pairs(event, pairs.data(), "
+                                "static_cast<uint8_t>(pairs.size()));\n");
+                        break;
+                    case JAVA_TYPE_BYTE_ARRAY:
+                        fprintf(out,
+                                "    stats_event_write_byte_array(event, "
+                                "reinterpret_cast<const uint8_t*>(arg%d.arg), arg%d.arg_length);\n",
+                                argIndex, argIndex);
+                        break;
+                    case JAVA_TYPE_BOOLEAN:
+                        fprintf(out, "    stats_event_write_bool(event, arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_INT: // Fall through.
+                    case JAVA_TYPE_ENUM:
+                        fprintf(out, "    stats_event_write_int32(event, arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_FLOAT:
+                        fprintf(out, "    stats_event_write_float(event, arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_LONG:
+                        fprintf(out, "    stats_event_write_int64(event, arg%d);\n", argIndex);
+                        break;
+                    case JAVA_TYPE_STRING:
+                        fprintf(out, "    stats_event_write_string8(event, arg%d);\n", argIndex);
+                        break;
+                    default:
+                        // Unsupported types: OBJECT, DOUBLE.
+                        fprintf(stderr, "Encountered unsupported type.");
+                        return 1;
+                }
+                argIndex++;
+            }
+            fprintf(out, "    const int ret = stats_event_write(event);\n");
+            fprintf(out, "    stats_event_release(event);\n");
+            fprintf(out, "    return ret;\n");
+        }
+        fprintf(out, "}\n\n");
+    }
+    return 0;
+}
+
+static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName) {
+    fprintf(out, "\n");
+    for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+            signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+        if (!signature_needed_for_module(signature_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_it->first;
+
+        write_native_method_signature(out, "int stats_write_non_chained", signature,
+                attributionDecl, " {");
+
+        vector<java_type_t> newSignature;
+
+        // First two args form the attribution node so size goes down by 1.
+        newSignature.reserve(signature.size() - 1);
+
+        // First arg is Attribution Chain.
+        newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
+
+        // Followed by the originial signature except the first 2 args.
+        newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
+
+        const char* uidName = attributionDecl.fields.front().name.c_str();
+        const char* tagName = attributionDecl.fields.back().name.c_str();
+        fprintf(out, "    const int32_t* %s = &arg1;\n", uidName);
+        fprintf(out, "    const size_t %s_length = 1;\n", uidName);
+        fprintf(out, "    const std::vector<char const*> %s(1, arg2);\n", tagName);
+        fprintf(out, "    return ");
+        write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
+
+        fprintf(out, "}\n\n");
+    }
+
+}
+#endif
+
+static void write_native_method_header(
+        FILE* out,
+        const string& methodName,
+        const map<vector<java_type_t>, set<string>>& signatures_to_modules,
+        const AtomDecl &attributionDecl, const string& moduleName) {
+
+    for (auto signature_to_modules_it = signatures_to_modules.begin();
+            signature_to_modules_it != signatures_to_modules.end(); signature_to_modules_it++) {
+        // Skip if this signature is not needed for the module.
+        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+            continue;
+        }
+
+        vector<java_type_t> signature = signature_to_modules_it->first;
+        write_native_method_signature(out, methodName, signature, attributionDecl, ";");
+    }
+}
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+                        const string& moduleName, const string& cppNamespace,
+                        const string& importHeader, const bool supportQ) {
+    // Print prelude
+    fprintf(out, "// This file is autogenerated\n");
+    fprintf(out, "\n");
+
+    fprintf(out, "#include <%s>\n", importHeader.c_str());
+#if defined(STATS_SCHEMA_LEGACY)
+    (void)supportQ; // Workaround for unused parameter error.
+    write_native_cpp_includes_q(out);
+#else
+    if (supportQ) {
+        fprintf(out, "#include <StatsEventCompat.h>\n");
+    } else {
+        fprintf(out, "#include <stats_event.h>\n");
+    }
+#endif
+
+    fprintf(out, "\n");
+    write_namespace(out, cppNamespace);
+
+#if defined(STATS_SCHEMA_LEGACY)
+    write_native_stats_log_cpp_globals_q(out);
+    write_native_get_timestamp_ns_q(out);
+    write_native_try_stats_write_methods_q(out, atoms, attributionDecl, moduleName);
+    write_native_stats_write_methods_q(out, "int stats_write", atoms, attributionDecl, moduleName,
+            "try_stats_write");
+    write_native_try_stats_write_non_chained_methods_q(out, atoms, attributionDecl, moduleName);
+    write_native_stats_write_non_chained_methods_q(out, "int stats_write_non_chained", atoms,
+            attributionDecl, moduleName, "try_stats_write_non_chained");
+#else
+    write_native_stats_write_methods(out, atoms, attributionDecl, moduleName, supportQ);
+    write_native_stats_write_non_chained_methods(out, atoms, attributionDecl, moduleName);
+#endif
+
+    // Print footer
+    fprintf(out, "\n");
+    write_closing_namespace(out, cppNamespace);
+
+    return 0;
+}
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+        const string& moduleName, const string& cppNamespace) {
+    // Print prelude
+    fprintf(out, "// This file is autogenerated\n");
+    fprintf(out, "\n");
+    fprintf(out, "#pragma once\n");
+    fprintf(out, "\n");
+    fprintf(out, "#include <stdint.h>\n");
+    fprintf(out, "#include <vector>\n");
+    fprintf(out, "#include <map>\n");
+    fprintf(out, "#include <set>\n");
+    fprintf(out, "\n");
+
+    write_namespace(out, cppNamespace);
+    fprintf(out, "\n");
+    fprintf(out, "/*\n");
+    fprintf(out, " * API For logging statistics events.\n");
+    fprintf(out, " */\n");
+    fprintf(out, "\n");
+
+    write_native_atom_constants(out, atoms, attributionDecl, moduleName);
+
+    // Print constants for the enum values.
+    fprintf(out, "//\n");
+    fprintf(out, "// Constants for enum values\n");
+    fprintf(out, "//\n\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+        atom != atoms.decls.end(); atom++) {
+        // Skip if the atom is not needed for the module.
+        if (!atom_needed_for_module(*atom, moduleName)) {
+            continue;
+        }
+
+        for (vector<AtomField>::const_iterator field = atom->fields.begin();
+            field != atom->fields.end(); field++) {
+            if (field->javaType == JAVA_TYPE_ENUM) {
+                fprintf(out, "// Values for %s.%s\n", atom->message.c_str(),
+                    field->name.c_str());
+                for (map<int, string>::const_iterator value = field->enumValues.begin();
+                    value != field->enumValues.end(); value++) {
+                    fprintf(out, "const int32_t %s__%s__%s = %d;\n",
+                        make_constant_name(atom->message).c_str(),
+                        make_constant_name(field->name).c_str(),
+                        make_constant_name(value->second).c_str(),
+                        value->first);
+                }
+                fprintf(out, "\n");
+            }
+        }
+    }
+
+    fprintf(out, "struct BytesField {\n");
+    fprintf(out,
+            "  BytesField(char const* array, size_t len) : arg(array), "
+            "arg_length(len) {}\n");
+    fprintf(out, "  char const* arg;\n");
+    fprintf(out, "  size_t arg_length;\n");
+    fprintf(out, "};\n");
+    fprintf(out, "\n");
+
+    // Print write methods
+    fprintf(out, "//\n");
+    fprintf(out, "// Write methods\n");
+    fprintf(out, "//\n");
+    write_native_method_header(out, "int stats_write", atoms.signatures_to_modules, attributionDecl,
+            moduleName);
+
+    fprintf(out, "//\n");
+    fprintf(out, "// Write flattened methods\n");
+    fprintf(out, "//\n");
+    write_native_method_header(out, "int stats_write_non_chained",
+            atoms.non_chained_signatures_to_modules, attributionDecl, moduleName);
+
+    fprintf(out, "\n");
+    write_closing_namespace(out, cppNamespace);
+
+    return 0;
+}
+
+}  // namespace stats_log_api_gen
+}  // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
new file mode 100644
index 0000000..aafa96e
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+int write_stats_log_cpp(FILE *out, const Atoms &atoms, const AtomDecl &attributionDecl,
+        const string& moduleName, const string& cppNamespace, const string& importHeader,
+        const bool supportQ);
+
+int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+        const string& moduleName, const string& cppNamespace);
+
+}  // namespace stats_log_api_gen
+}  // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.cpp b/tools/stats_log_api_gen/native_writer_q.cpp
new file mode 100644
index 0000000..299873d
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.cpp
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+#include "native_writer_q.h"
+#include "utils.h"
+
+namespace android {
+namespace stats_log_api_gen {
+
+static void write_native_stats_write_body_q(FILE* out, const vector<java_type_t>& signature,
+        const AtomDecl& attributionDecl, const string& indent, const string& tryMethodName) {
+    fprintf(out, "%sint ret = 0;\n", indent.c_str());
+
+    fprintf(out, "%sfor(int retry = 0; retry < 2; ++retry) {\n", indent.c_str());
+    fprintf(out, "%s    ret = ", indent.c_str());
+    write_native_method_call(out, tryMethodName, signature, attributionDecl);
+    fprintf(out, "%s    if (ret >= 0) { break; }\n", indent.c_str());
+
+    fprintf(out, "%s    {\n", indent.c_str());
+    fprintf(out, "%s        std::lock_guard<std::mutex> lock(mLogdRetryMutex);\n", indent.c_str());
+    fprintf(out, "%s        if ((get_elapsed_realtime_ns() - lastRetryTimestampNs) <= "
+                            "kMinRetryIntervalNs) break;\n", indent.c_str());
+    fprintf(out, "%s        lastRetryTimestampNs = get_elapsed_realtime_ns();\n",
+            indent.c_str());
+    fprintf(out, "%s    }\n", indent.c_str());
+    fprintf(out, "%s    std::this_thread::sleep_for(std::chrono::milliseconds(10));\n",
+            indent.c_str());
+    fprintf(out, "%s}\n", indent.c_str());
+    fprintf(out, "%sif (ret < 0) {\n", indent.c_str());
+    fprintf(out, "%s    note_log_drop(ret, code);\n", indent.c_str());
+    fprintf(out, "%s}\n", indent.c_str());
+    fprintf(out, "%sreturn ret;\n", indent.c_str());
+}
+
+void write_native_cpp_includes_q(FILE* out) {
+    fprintf(out, "#include <mutex>\n");
+    fprintf(out, "#include <chrono>\n");
+    fprintf(out, "#include <thread>\n");
+    fprintf(out, "#ifdef __ANDROID__\n");
+    fprintf(out, "#include <cutils/properties.h>\n");
+    fprintf(out, "#endif\n");
+    fprintf(out, "#include <stats_event_list.h>\n");
+    fprintf(out, "#include <log/log.h>\n");
+    fprintf(out, "#include <time.h>\n");
+}
+
+void write_native_get_timestamp_ns_q(FILE* out) {
+    fprintf(out, "\n");
+    fprintf(out, "static int64_t get_elapsed_realtime_ns() {\n");
+    fprintf(out, "    struct timespec t;\n");
+    fprintf(out, "    t.tv_sec = t.tv_nsec = 0;\n");
+    fprintf(out, "    clock_gettime(CLOCK_BOOTTIME, &t);\n");
+    fprintf(out, "    return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec;\n");
+    fprintf(out, "}\n");
+}
+
+void write_native_stats_log_cpp_globals_q(FILE* out) {
+    fprintf(out, "// the single event tag id for all stats logs\n");
+    fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+    fprintf(out, "#ifdef __ANDROID__\n");
+    fprintf(out,
+            "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+    fprintf(out, "#else\n");
+    fprintf(out, "const static bool kStatsdEnabled = false;\n");
+    fprintf(out, "#endif\n");
+
+    fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
+    fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
+    fprintf(out, "static std::mutex mLogdRetryMutex;\n");
+}
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName) {
+    fprintf(out, "\n");
+    for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+        signature_to_modules_it != atoms.signatures_to_modules.end(); signature_to_modules_it++) {
+        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_to_modules_it->first;
+
+        write_native_method_signature(out, "static int try_stats_write", signature,
+                attributionDecl, " {");
+
+        int argIndex = 1;
+        fprintf(out, "  if (kStatsdEnabled) {\n");
+        fprintf(out, "    stats_event_list event(kStatsEventTag);\n");
+        fprintf(out, "    event << get_elapsed_realtime_ns();\n\n");
+        fprintf(out, "    event << code;\n\n");
+        for (vector<java_type_t>::const_iterator arg = signature.begin();
+            arg != signature.end(); arg++) {
+            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+                for (const auto &chainField : attributionDecl.fields) {
+                    if (chainField.javaType == JAVA_TYPE_STRING) {
+                        fprintf(out, "    if (%s_length != %s.size()) {\n",
+                            attributionDecl.fields.front().name.c_str(), chainField.name.c_str());
+                        fprintf(out, "        return -EINVAL;\n");
+                        fprintf(out, "    }\n");
+                    }
+                }
+                fprintf(out, "\n    event.begin();\n");
+                fprintf(out, "    for (size_t i = 0; i < %s_length; ++i) {\n",
+                    attributionDecl.fields.front().name.c_str());
+                fprintf(out, "        event.begin();\n");
+                for (const auto &chainField : attributionDecl.fields) {
+                    if (chainField.javaType == JAVA_TYPE_STRING) {
+                        fprintf(out, "        if (%s[i] != NULL) {\n", chainField.name.c_str());
+                        fprintf(out, "           event << %s[i];\n", chainField.name.c_str());
+                        fprintf(out, "        } else {\n");
+                        fprintf(out, "           event << \"\";\n");
+                        fprintf(out, "        }\n");
+                    } else {
+                        fprintf(out, "        event << %s[i];\n", chainField.name.c_str());
+                    }
+                }
+                fprintf(out, "        event.end();\n");
+                fprintf(out, "    }\n");
+                fprintf(out, "    event.end();\n\n");
+            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+                    fprintf(out, "    event.begin();\n\n");
+                    fprintf(out, "    for (const auto& it : arg%d_1) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    for (const auto& it : arg%d_2) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    for (const auto& it : arg%d_3) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    for (const auto& it : arg%d_4) {\n", argIndex);
+                    fprintf(out, "         event.begin();\n");
+                    fprintf(out, "         event << it.first;\n");
+                    fprintf(out, "         event << it.second;\n");
+                    fprintf(out, "         event.end();\n");
+                    fprintf(out, "    }\n");
+
+                    fprintf(out, "    event.end();\n\n");
+            } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+                fprintf(out,
+                        "    event.AppendCharArray(arg%d.arg, "
+                        "arg%d.arg_length);\n",
+                        argIndex, argIndex);
+            } else {
+                if (*arg == JAVA_TYPE_STRING) {
+                    fprintf(out, "    if (arg%d == NULL) {\n", argIndex);
+                    fprintf(out, "        arg%d = \"\";\n", argIndex);
+                    fprintf(out, "    }\n");
+                }
+                fprintf(out, "    event << arg%d;\n", argIndex);
+            }
+            argIndex++;
+        }
+
+        fprintf(out, "    return event.write(LOG_ID_STATS);\n");
+        fprintf(out, "  } else {\n");
+        fprintf(out, "    return 1;\n");
+        fprintf(out, "  }\n");
+        fprintf(out, "}\n");
+        fprintf(out, "\n");
+    }
+
+}
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName) {
+    for (auto signature_to_modules_it = atoms.signatures_to_modules.begin();
+        signature_to_modules_it != atoms.signatures_to_modules.end();
+        signature_to_modules_it++) {
+        if (!signature_needed_for_module(signature_to_modules_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_to_modules_it->first;
+
+        write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+        write_native_stats_write_body_q(out, signature, attributionDecl, "    ", tryMethodName);
+        fprintf(out, "}\n\n");
+    }
+}
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+        const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+        const string& tryMethodName) {
+    for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+            signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+        if (!signature_needed_for_module(signature_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_it->first;
+
+        write_native_method_signature(out, methodName, signature, attributionDecl, " {");
+
+        write_native_stats_write_body_q(out, signature, attributionDecl, "    ", tryMethodName);
+        fprintf(out, "}\n\n");
+    }
+}
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName) {
+    for (auto signature_it = atoms.non_chained_signatures_to_modules.begin();
+            signature_it != atoms.non_chained_signatures_to_modules.end(); signature_it++) {
+        if (!signature_needed_for_module(signature_it->second, moduleName)) {
+            continue;
+        }
+        vector<java_type_t> signature = signature_it->first;
+
+        write_native_method_signature(out, "static int try_stats_write_non_chained", signature,
+                attributionDecl, " {");
+
+        int argIndex = 1;
+        fprintf(out, "  if (kStatsdEnabled) {\n");
+        fprintf(out, "    stats_event_list event(kStatsEventTag);\n");
+        fprintf(out, "    event << get_elapsed_realtime_ns();\n\n");
+        fprintf(out, "    event << code;\n\n");
+        for (vector<java_type_t>::const_iterator arg = signature.begin();
+            arg != signature.end(); arg++) {
+            if (argIndex == 1) {
+                fprintf(out, "    event.begin();\n\n");
+                fprintf(out, "    event.begin();\n");
+            }
+            if (*arg == JAVA_TYPE_STRING) {
+                fprintf(out, "    if (arg%d == NULL) {\n", argIndex);
+                fprintf(out, "        arg%d = \"\";\n", argIndex);
+                fprintf(out, "    }\n");
+            }
+            if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+                fprintf(out,
+                        "    event.AppendCharArray(arg%d.arg, "
+                        "arg%d.arg_length);\n",
+                        argIndex, argIndex);
+            } else {
+                fprintf(out, "    event << arg%d;\n", argIndex);
+            }
+            if (argIndex == 2) {
+                fprintf(out, "    event.end();\n\n");
+                fprintf(out, "    event.end();\n\n");
+            }
+            argIndex++;
+        }
+
+        fprintf(out, "    return event.write(LOG_ID_STATS);\n");
+        fprintf(out, "  } else {\n");
+        fprintf(out, "    return 1;\n");
+        fprintf(out, "  }\n");
+        fprintf(out, "}\n");
+        fprintf(out, "\n");
+    }
+}
+
+}  // namespace stats_log_api_gen
+}  // namespace android
diff --git a/tools/stats_log_api_gen/native_writer_q.h b/tools/stats_log_api_gen/native_writer_q.h
new file mode 100644
index 0000000..a2ab1ae
--- /dev/null
+++ b/tools/stats_log_api_gen/native_writer_q.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Collation.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace stats_log_api_gen {
+
+using namespace std;
+
+void write_native_cpp_includes_q(FILE* out);
+
+void write_native_stats_log_cpp_globals_q(FILE* out);
+
+void write_native_try_stats_write_methods_q(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_methods_q(FILE* out, const string& methodName, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName, const string& tryMethodName);
+
+void write_native_try_stats_write_non_chained_methods_q(FILE* out, const Atoms& atoms,
+        const AtomDecl& attributionDecl, const string& moduleName);
+
+void write_native_stats_write_non_chained_methods_q(FILE* out, const string& methodName,
+        const Atoms& atoms, const AtomDecl& attributionDecl, const string& moduleName,
+        const string& tryMethodName);
+
+void write_native_get_timestamp_ns_q(FILE* out);
+
+}  // namespace stats_log_api_gen
+}  // namespace android
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index c3e70382..c9a4763 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -229,8 +229,8 @@
 
 message ModuleAtoms {
     oneof event {
-        ModuleOneAtom module_one_atom = 1 [(android.os.statsd.log_from_module) = "module1"];
-        ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.log_from_module) = "module2"];
+        ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"];
+        ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"];
         NoModuleAtom no_module_atom = 3;
     }
-}
\ No newline at end of file
+}
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index d6cfe95..c65d190 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -204,6 +204,65 @@
     fprintf(out, "\n");
 }
 
+void write_native_method_signature(FILE* out, const string& methodName,
+        const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+        const string& closer) {
+    fprintf(out, "%s(int32_t code", methodName.c_str());
+    int argIndex = 1;
+    for (vector<java_type_t>::const_iterator arg = signature.begin();
+        arg != signature.end(); arg++) {
+        if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+            for (auto chainField : attributionDecl.fields) {
+                if (chainField.javaType == JAVA_TYPE_STRING) {
+                        fprintf(out, ", const std::vector<%s>& %s",
+                             cpp_type_name(chainField.javaType),
+                             chainField.name.c_str());
+                } else {
+                        fprintf(out, ", const %s* %s, size_t %s_length",
+                             cpp_type_name(chainField.javaType),
+                             chainField.name.c_str(), chainField.name.c_str());
+                }
+            }
+        } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+            fprintf(out, ", const std::map<int, int32_t>& arg%d_1, "
+                         "const std::map<int, int64_t>& arg%d_2, "
+                         "const std::map<int, char const*>& arg%d_3, "
+                         "const std::map<int, float>& arg%d_4",
+                         argIndex, argIndex, argIndex, argIndex);
+        } else {
+            fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
+        }
+        argIndex++;
+    }
+    fprintf(out, ")%s\n", closer.c_str());
+}
+
+void write_native_method_call(FILE* out, const string& methodName,
+        const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex) {
+    fprintf(out, "%s(code", methodName.c_str());
+    for (vector<java_type_t>::const_iterator arg = signature.begin();
+       arg != signature.end(); arg++) {
+       if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
+           for (auto chainField : attributionDecl.fields) {
+               if (chainField.javaType == JAVA_TYPE_STRING) {
+                       fprintf(out, ", %s",
+                            chainField.name.c_str());
+               } else {
+                       fprintf(out, ",  %s,  %s_length",
+                            chainField.name.c_str(), chainField.name.c_str());
+               }
+           }
+       } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
+           fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex,
+                   argIndex, argIndex, argIndex);
+       } else {
+           fprintf(out, ", arg%d", argIndex);
+       }
+       argIndex++;
+    }
+    fprintf(out, ");\n");
+}
+
 // Java
 void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName) {
     fprintf(out, "    // Constants for atom codes.\n");
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index a89387f..50737a6 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -56,8 +56,14 @@
 void write_closing_namespace(FILE* out, const string& cppNamespaces);
 
 void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-        const string& moduleName
-);
+        const string& moduleName);
+
+void write_native_method_signature(FILE* out, const string& methodName,
+        const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
+        const string& closer);
+
+void write_native_method_call(FILE* out, const string& methodName,
+        const vector<java_type_t>& signature, const AtomDecl& attributionDecl, int argIndex = 1);
 
 // Common Java helpers.
 void write_java_atom_codes(FILE* out, const Atoms& atoms, const string& moduleName);
@@ -69,14 +75,12 @@
 
 int write_java_non_chained_methods(FILE* out, const map<vector<java_type_t>,
         set<string>>& signatures_to_modules,
-        const string& moduleName
-);
+        const string& moduleName);
 
 int write_java_work_source_methods(
         FILE* out,
         const map<vector<java_type_t>, set<string>>& signatures_to_modules,
-        const string& moduleName
-);
+        const string& moduleName);
 
 }  // namespace stats_log_api_gen
 }  // namespace android
diff --git a/wifi/Android.bp b/wifi/Android.bp
index fb1f866..8155922 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -42,11 +42,21 @@
     srcs: ["java/android/net/wifi/WifiAnnotations.java"],
 }
 
+// list of tests that are allowed to access @hide APIs from framework-wifi
+test_access_hidden_api_whitelist = [
+    "//frameworks/base/wifi/tests",
+    "//frameworks/opt/net/wifi/tests/wifitests:__subpackages__",
+
+    "//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests",
+]
+
 java_library {
     name: "framework-wifi",
-    sdk_version: "core_platform", // TODO(b/140299412) should be core_current
+    // TODO(b/140299412) should be core_current once we build against framework-system-stubs
+    sdk_version: "core_platform",
     libs: [
-        "framework-minus-apex", // TODO(b/140299412) should be framework-system-stubs
+        // TODO(b/140299412) should be framework-system-stubs once we fix all @hide dependencies
+        "framework-minus-apex",
     ],
     srcs: [
         ":framework-wifi-updatable-sources",
@@ -54,7 +64,11 @@
     installable: true,
     optimize: {
         enabled: false
-    }
+    },
+    visibility: [
+        "//frameworks/base", // TODO(b/140299412) remove once all dependencies are fixed
+        "//frameworks/opt/net/wifi/service:__subpackages__",
+    ] + test_access_hidden_api_whitelist,
 }
 
 droidstubs {
@@ -84,3 +98,16 @@
     installable: false,
 }
 
+// defaults for tests that need to build against framework-wifi's @hide APIs
+java_defaults {
+    name: "framework-wifi-test-defaults",
+    sdk_version: "core_platform", // tests can use @CorePlatformApi's
+    libs: [
+        "framework-wifi",
+        "framework-minus-apex",
+
+        // if sdk_version="" this gets automatically included, but here we need to add manually.
+        "framework-res",
+    ],
+    visibility: test_access_hidden_api_whitelist,
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e3a945d..2a165d3 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2446,10 +2446,14 @@
         return key;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+    /**
+     * Get the IpConfiguration object associated with this WifiConfiguration.
+     * @hide
+     */
+    @NonNull
+    @SystemApi
     public IpConfiguration getIpConfiguration() {
-        return mIpConfiguration;
+        return new IpConfiguration(mIpConfiguration);
     }
 
     /**